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

21
app/admin/main/dm/BUILD Normal file
View File

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

View File

@@ -0,0 +1,434 @@
# 弹幕管理后台
#### V4.6.5
> 1. fix dm mid=0
#### V4.6.4
> 1. 更新最新弹幕索引
#### V4.6.3
> 1. 弹幕发送黑名单
#### V4.6.2
> 1. remove cache.Cache
#### V4.6.1
> 1. 接入account grpc
#### V4.6.0
> 1. 列表接口从manager解耦
> 2. 弹幕id 添加string返回
#### V4.5.9
> 1. fix 弹幕count
#### V4.5.8
> 1. fix 弹幕计数
#### V4.5.7
> 1. 弹幕蒙版参数
#### V4.5.6
> 1. 弹幕任务下载csv
#### V4.5.5
> 1. 弹幕任务接口迭代
#### V4.5.4
> 1. 弹幕日志增加任务删除状态
#### V4.5.3
> 1. 字幕开关
#### V4.5.2
> 1. dm mask add mid
#### V4.5.1
> 1. remove addSlashes
#### V4.5.0
> 1. 弹幕大型任务
#### V4.4.6
> 1. 聚合搜索更新弹幕状态请求 fix
#### V4.4.5
> 1. 聚合搜索更新弹幕状态请求
#### V4.4.4
> 1. 增加web蒙版
#### V4.4.3
> 1. 字幕举报忽略01mode
#### V4.4.2
> 1. 字幕语言返回map
#### V4.4.1
> 1. 添加稿件字幕开关
#### V4.4.0
> 1. 添加字幕举报回调
#### V4.3.22
> 1. 弹幕蒙版灰度up主名单 fix
#### V4.3.21
> 1. 增加弹幕蒙版灰度up主名单
#### V4.3.20
> 1. rebuild
#### V4.3.19
> 1. 添加字幕后台
#### V4.3.18
> 1. 将弹幕管理操作日志上报到额外的logid
#### V4.3.17
> 1. 更新弹幕上限接口参数
#### V4.3.16
> 1. 更新搜索索引对接es v3
#### V4.3.15
> 1. 弹幕统计搜索接口替换
#### V4.3.14
> 1. 弹幕统计搜索接口替换
#### V4.3.13
> 1. 更改弹幕列表默认排序字段为ctime
#### V4.3.12
> 1. 激活弹幕池更改权限
#### V4.3.11
> 1. 增加弹幕蒙版管理
#### V4.3.10
> 1. dm搜索 kwmsg
#### V4.3.9
> 1. fix UName
#### V4.3.8
> 1. manager后台增加搜索
> 2. 弹幕池审核对接日志平台
> 3. 使用bm.NewServer()
#### V4.3.7
> 1. 弹幕监控索引更新
#### V4.3.6
> 1. 迁移identify-->verify
#### V4.3.5
> 1. 封禁小黑屋接口拆分
#### V4.3.4
> 1. elastic.LikeLevelLow
#### V4.3.3
> 1. fix dm search nil
#### V4.3.2
> 1. dm search and dm_report refactor
#### V4.3.1
> 1. 修复特殊弾幕内容显示不正确的bug
#### V4.3.0
> 1. report search refactor
#### V4.2.4
> 1. 修复弹幕管理中的计数bug
#### V4.2.3
> 1. acount,count的变更改为操作新库
#### V4.2.2
> 1. build master
#### V4.2.1
> 1. state,maxlimit,childpool的变更改为操作新库
> 2. 移除mid的同步接口
#### V4.2.0
> 1. update infoc sdk
#### V4.1.12
> 2. 弹幕举报删除时更新计数表
#### V4.1.11
> 1. 稿件弹幕列表使用弹幕新库
#### V4.1.10
> 1. 移除根据视频时长更改弹幕上限的限制最大上限20000
#### V4.1.9
> 1. 变更删除举报弹幕时的弹幕状态为举报删除
#### V4.1.8
> 1. 弹幕池变更时更新move_cnt以及childpool
#### V4.1.7
> 1. 编辑UP主屏蔽词后删除缓存
#### V4.1.6
> 1. 弹幕管理弹幕状态和弹幕池支持多选
#### V4.1.5
> 1. 修复编辑UP主屏蔽底端弹幕等bug
#### V4.1.4
> 1. 修复编辑UP主屏蔽词bug
#### V4.1.3
> 1. 添加UP主屏蔽词高级弹幕列表弹幕转移日志
#### V4.1.2
> 1. 弹幕举报列表中弹幕状态返回数据库对应状态
#### V4.1.1
> 1. dm_subject新增字段
#### V4.1.0
> 1. 使用blademaster
#### V4.0.8
> 1. 添加举报积分
#### V4.0.7
> 1. 迁移至main目录
#### V4.0.6
> 1. 使用account-service v7
> 2. dao.Subject返回关闭状态主题
#### V4.0.5
> 1. 修复待审弹幕数不准确的问题
#### V4.0.4
> 1. 修复一二审删除时操作日志重复的问题
#### V4.0.3
> 1. 修复弹幕管理搜索索引更新
#### V4.0.2
> 1. 修复subject不存在导致的panic
#### V4.0.1
> 1. 修复一审、二审相互转换时导致的弹幕状态恢复bug
#### V4.0.0
> 1. 重构弹幕管理功能
> 2. 重构弹幕监控功能
#### V3.9.19
> 1. 弹幕举报新增举报理由
> 2. 弹幕举报处理新增封禁理由
#### V3.9.18
> 1. 重设版本号
#### V3.9.17
> 1. 调整弹幕一二审详细日志上报
#### V3.9.16
> 1. 弹幕保护状态上报日志状态
#### V3.9.15
> 1. 调整berserker数据平台日志接口参数
#### V3.9.14
> 1. 查询数据平台日志
#### V3.9.13
> 1. test 去除 simplejson 依赖
#### V3.9.12
> 1. 弹幕举报处理日志
#### V3.9.11
> 1. 新的弹幕后台举报理由处理
#### V3.9.10
> 1. 修复添加监控视频时的并发问题
#### V3.9.9
> 1. fix_count 读取 post aid 参数
#### V3.9.8
> 1. 弹幕风纪委添加business_time
#### V3.9.7
> 1. 弹幕修改状态同步新老库
#### V3.9.6
> 1. 增加修复稿件弹幕计数接口
#### V3.9.5
> 1. 调整更新搜索的时机
> 2. 弹幕举报添加发送者id
#### V3.9.4
> 1. 弹幕搜索接新库
#### V3.9.3
> 1. 修改http层管理员参数解析
> 2. 添加上报infoc日志的管理员操作描述
#### V3.9.2
> 1. 修改http层管理员参数解析
#### V3.9.1
> 1. 调整弹幕监控相关代码结构
> 2. 调整弹幕举报相关代码结构
#### V3.9.0
> 1. 添加infoc业务操作日志
#### V3.8.5
> 1. 修复弹幕监控重复添加的问题
#### V3.8.4
> 1. 修改弹幕发送时间bug
#### V3.8.3
> 1. 弹幕列表对接新库
#### V3.8.2
> 1. 并发获取举报用户的问题
#### V3.8.1
> 1. 移除无用的代码
#### V3.8.0
> 1. 弹幕举报删除对接信用分
> 2. 更新弹幕举报model
> 3. 初始化举报用户空列表
#### V3.7.6
> 1. 弹幕举报对接新风纪委
#### V3.7.5
> 1. dm_count 计数修改
#### V3.7.4
> 1. 弹幕监控双写dm_subject
#### V3.7.3
> 1. Archive2 to Archive3
> 2. Video2 to Video3
#### version 3.7.2
> 1. 移除dao层mysql prepare
#### version 3.7.1
> 1. 弹幕池列表页重构
#### version 3.7.0
> 1. 弹幕监控需求
#### version 3.6.2
> 1. 弹幕管理更新搜索代码优化
#### version 3.6.1
> 1. 弹幕管理并发更新搜索
#### version 3.6.0
> 1. 弹幕管理迁移大仓库
> 2. 更新基础依赖
#### version 3.5.7
> 1. 更改弹幕举报扣节操理由为管理员更改理由
#### version 3.5.6
> 1. 修复弹幕列表获取中的bug
> 2. 移除异步逻辑中return error
#### version 3.5.5
> 1. 优化弹幕列表获取排序功能
#### version 3.5.4
> 1. 请求稿件rpc 频率 && 小黑屋封禁bug修复
#### version 3.5.3
> 1. 合并弹幕举报发送通知功能到dm-admin
#### version 3.5.2
> 1. 弹幕状态批量修改优化
#### version 3.5.1
> 1. 弹幕状态批量修改优化
#### version 3.5.0
> 1. 升级go-common,go-business
#### version 3.4.1
> 1. 并发获取稿件详情
> 2. 并发获取弹幕内容
> 3. 并发获取举报用户,同一张表下的举报用户批量获取再拼接
> 4. 异步扣节操,封禁,发送信息
#### version 3.4
> 1. 弹幕举报发送通知功能从manager后台迁移到dm-admin
#### version 3.3
> 1. 弹幕举报一二审流程优化
> 2. 弹幕管理界面操作优化
#### version 3.2.10
> 1. 修改verify service
#### V3.2.9
> 1. 增加ping接口详细报错信息
> 2. 移除多余的router
> 3. 优化弹幕举报状态变更为批量接口
#### V3.2.4
> 1. 弹幕举报搜索跟新接口优化
#### V3.2.3
> 1. 弹幕举报获取单个详情添加start参数
#### V3.2.2
> 1. 修复搜索强制更新bug
#### V3.2.1
> 1. 对接搜索获取举报详情的参数修改
##### V3.2.0
> 1. 增加弹幕举报
##### V3.1.9
> 1. fix bug
##### V3.1.8
> 1. 整理代码格式
##### V3.1.7
> 1. 修复扣节操的bug
##### V3.1.6
> 1. 修改列表的ip为string
##### V3.1.5
> 1. 去除掉最近7天的逻辑
##### V3.1.4
> 1. 更新log,删除多余配置
##### V3.1.3
> 1. 修复bug
> 2. 优化列表查询
##### V3.1.2
> 1. 修复url单词
##### V3.1.1
> 1. 修改弹幕管理批量接口扣节操逻辑
##### V3.1.0
> 1. 弹幕内容管理

View File

@@ -0,0 +1,12 @@
# Owner
liangkai
renwei
# Author
fengduzhen
guhao
liangkai
# Reviewer
liangkai
renwei

19
app/admin/main/dm/OWNERS Normal file
View File

@@ -0,0 +1,19 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- fengduzhen
- guhao
- liangkai
- renwei
labels:
- admin
- admin/main/dm
- main
options:
no_parent_owners: true
reviewers:
- fengduzhen
- guhao
- liangkai
- renwei
- renyashun

View File

@@ -0,0 +1 @@
### 弹幕管理后台

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 = ["dm-admin-test.toml"],
importpath = "go-common/app/admin/main/dm/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/dm/conf:go_default_library",
"//app/admin/main/dm/http:go_default_library",
"//app/admin/main/dm/service:go_default_library",
"//library/ecode/tip:go_default_library",
"//library/log:go_default_library",
"//library/net/trace:go_default_library",
"//library/queue/databus/report: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,243 @@
# This is a TOML config file.
[infoc2]
taskID = "000279"
proto = "tcp"
addr = "172.18.33.125:15140"
chanSize = 10240
[infocBak]
taskID = "000279"
proto = "tcp"
addr = "172.18.33.125:15140"
chanSize = 10240
[httpServer]
addr = "0.0.0.0:6311"
maxListen = 100
timeout = "10s"
[db]
[db.dm]
addr = "172.16.33.205:3308"
dsn = "test:test@tcp(172.16.33.205:3308)/bilibili_dm?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8"
active = 10
idle = 5
idleTimeout ="4h"
queryTimeout = "500ms"
execTimeout = "500ms"
tranTimeout = "500ms"
[db.dm.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[db.dmMetaWriter]
addr = "172.16.33.205:3310"
dsn = "test_3308:test_3308@tcp(172.16.33.205:3310)/bilibili_dm_meta?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8mb4"
active = 10
idle = 5
idleTimeout ="4h"
queryTimeout = "500ms"
execTimeout = "500ms"
tranTimeout = "500ms"
[db.dmMetaWriter.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[db.dmMetaReader]
addr = "172.16.33.205:3310"
dsn = "test_3308:test_3308@tcp(172.16.33.205:3310)/bilibili_dm_meta?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8mb4"
active = 10
idle = 5
idleTimeout ="4h"
queryTimeout = "500ms"
execTimeout = "500ms"
tranTimeout = "500ms"
[db.dmMetaReader.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[memcache]
[memcache.filter]
name = "filter"
proto = "tcp"
addr = "172.16.33.54:11211"
idle = 5
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
[memcache.subtitle]
name = "dm2"
proto = "tcp"
addr = "172.16.33.54:11211"
idle = 5
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
[host]
api = "http://api.bilibili.co"
videoup = "http://archive.api.bilibili.co"
search = "http://uat-manager.bilibili.co"
season = "http://uat-manager.bilibili.co"
message = "http://message.bilibili.co"
account = "http://account.bilibili.co"
mask = "http://172.22.33.111:8200"
berserker = "http://berserker.bilibili.co/avenger/api/148/query"
[httpClient]
key = "f6433799dbd88751"
secret = "36f8ddb1806207fe07013ab6a77a3935"
dial = "1s"
timeout = "2s"
keepAlive = "60s"
timer = 1000
[httpClient.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[httpSearch]
key = "89ffc6e896106fd3"
secret = "1359cdbaf9ff6e2f9b6251579d966101"
dial = "1s"
timeout = "8s"
keepAlive = "60s"
timer = 1000
[httpSearch.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[httpInfoc]
infocQueryURL = "http://172.18.33.160:6010/avenger/api/2/query"
key = "f43ae8af9179884d0f7e3d6e532dd1bd"
secret = "3e4078b4e9448ef12528b68a22c1fa60"
dial = "1s"
timeout = "2s"
keepAlive = "60s"
timer = 1000
[httpInfoc.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[accountRPC]
timeout = "2s"
[archiveRPC]
timeout = "1s"
[actionpub]
key = "0Pub71WwEMKXu63qtztu"
secret= "0Pub71WwEMKXu63qtztv"
group= "DMAction-UGC-P"
topic= "DMAction-T"
action="pub"
name = "dm-job"
proto = "tcp"
addr = "172.16.33.158:6205"
active = 5
idle = 1
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
[managerAuth]
managerHost = "http://uat-manager.bilibili.co"
dashboardHost = "http://dashboard-mng.bilibili.co"
dashboardCaller = "manager-go"
[managerAuth.dsHTTPClient]
key = "manager-go"
secret = "949bbb2dd3178252638c2407578bc7ad"
dial = "1s"
timeout = "3s"
keepAlive = "60s"
timer = 1000
[managerAuth.dsHTTPClient.breaker]
window ="3s"
sleep ="100ms"
bucket = 10
ratio = 0.5
request = 100
[managerAuth.maHTTPClient]
key = "f6433799dbd88751"
secret = "36f8ddb1806207fe07013ab6a77a3935"
dial = "1s"
timeout = "3s"
keepAlive = "60s"
timer = 1000
[managerAuth.maHTTPClient.breaker]
window ="3s"
sleep ="100ms"
bucket = 10
ratio = 0.5
request = 100
[managerAuth.session]
sessionIDLength = 32
cookieLifeTime = 1800
cookieName = "mng-go"
domain = ".bilibili.co"
[managerAuth.session.Memcache]
name = "dmadmin-auth"
proto = "tcp"
addr = "172.16.33.54:11211"
active = 10
idle = 5
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
[elastic]
host = "http://uat-manager.bilibili.co"
[elastic.HTTPClient]
key = "manager-go"
secret = "949bbb2dd3178252638c2407578bc7ad"
dial = "1s"
timeout = "3s"
keepAlive = "60s"
timer = 1000
[elastic.HTTPClient.breaker]
window ="3s"
sleep ="100ms"
bucket = 10
ratio = 0.5
request = 100
[managerLog]
Key = "2511663d546f1413"
Secret = "cde3b480836cc76df3d635470f991caa"
Group = "LogAudit-MainSearch-P"
Topic = "LogAudit-T"
Action = "pub"
Buffer = 10240
Name = "log-audit/log-sub"
Proto = "tcp"
Addr = "172.18.33.50:6205"
Active = 10
Idle = 5
DialTimeout = "200ms"
ReadTimeout = "200ms"
WriteTimeout = "200ms"
IdleTimeout = "80s"

View File

@@ -0,0 +1,58 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"time"
"go-common/app/admin/main/dm/conf"
"go-common/app/admin/main/dm/http"
"go-common/app/admin/main/dm/service"
ecode "go-common/library/ecode/tip"
"go-common/library/log"
"go-common/library/net/trace"
manager "go-common/library/queue/databus/report"
)
func main() {
flag.Parse()
if err := conf.Init(); err != nil {
log.Error("conf.Init() error(%v)", err)
panic(err)
}
// init log
log.Init(conf.Conf.Xlog)
trace.Init(conf.Conf.Tracer)
defer trace.Close()
defer func() {
log.Close()
// wait for a while to guarantee that all log messages are written
time.Sleep(10 * time.Millisecond)
}()
// ecode init
ecode.Init(conf.Conf.Ecode)
// manager log init
manager.InitManager(conf.Conf.ManagerLog)
// service init
svc := service.New(conf.Conf)
http.Init(conf.Conf, svc)
log.Info("dm-admin start")
// init signal
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("dm-admin get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGSTOP, syscall.SIGINT:
log.Info("dm-admin exit")
return
case syscall.SIGHUP:
// TODO reload
default:
return
}
}
}

View File

@@ -0,0 +1,46 @@
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/admin/main/dm/conf",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/cache/memcache:go_default_library",
"//library/conf:go_default_library",
"//library/database/bfs:go_default_library",
"//library/database/elastic: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/permit:go_default_library",
"//library/net/http/blademaster/middleware/verify:go_default_library",
"//library/net/rpc: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,184 @@
package conf
import (
"errors"
"flag"
"go-common/library/cache/memcache"
"go-common/library/conf"
"go-common/library/database/bfs"
"go-common/library/database/elastic"
"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/permit"
"go-common/library/net/http/blademaster/middleware/verify"
"go-common/library/net/rpc"
"go-common/library/net/rpc/warden"
"go-common/library/net/trace"
"go-common/library/queue/databus"
"github.com/BurntSushi/toml"
)
//Conf config var
var (
ConfPath string
client *conf.Client
Conf = &Config{}
)
//Config Config
type Config struct {
// base
// ecode
Ecode *ecode.Config
// log
Xlog *log.Config
Infoc2 *infoc.Config
InfocBak *infoc.Config
Verify *verify.Config
// rpc client
AccountRPC *warden.ClientConfig
// rpc client
ArchiveRPC *rpc.ClientConfig
// http server config
HTTPServer *bm.ServerConfig
// db
DB *DB
// memcache
Memcache *Memcache
// http client
HTTPClient *HTTPClient
// http client of search
HTTPSearch *HTTPSearch
// http client of Infoc Data
HTTPInfoc *HTTPInfoc
// tracer
Tracer *trace.Config
// databus client
ActionPub *databus.Config
Host Host
ManagerAuth *permit.Config
// elastic config
Elastic *elastic.Config
// manager log config
ManagerLog *databus.Config
//bfs config
BFS *bfs.Config
}
// DB mysql config struct
type DB struct {
DM *sql.Config
DMMetaWriter *sql.Config
DMMetaReader *sql.Config
}
// Memcache dm memcache
type Memcache struct {
Filter *struct {
*memcache.Config
}
Subtitle *struct {
*memcache.Config
}
}
// DMReport dm report
type DMReport struct {
Count int64
MsgURL string
MoralURL string
BlockURL string
}
// Host hosts used in dm admin
type Host struct {
Videoup string
API string
Search string
Season string
Message string
Account string
Mask string
Berserker string
}
// HTTPClient http client
type HTTPClient struct {
*bm.ClientConfig
JudgeURL string
ArcInfoURL string
CidAidsURL string
TypeInfoURL string
}
// HTTPSearch http client of search
type HTTPSearch struct {
*bm.ClientConfig
SearchURL string
UpdateURL string
ReportURL string
UpdateOldURL string
CountURL string
}
// HTTPInfoc http client of Infoc query
type HTTPInfoc struct {
*bm.ClientConfig
InfocQueryURL string
}
func init() {
flag.StringVar(&ConfPath, "conf", "", "config path")
}
//Init int config
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
}

104
app/admin/main/dm/dao/BUILD Normal file
View File

@@ -0,0 +1,104 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"account_test.go",
"credit_test.go",
"dao_test.go",
"mask_test.go",
"mc_filter_test.go",
"mc_subtitle_test.go",
"message_test.go",
"mysql_advance_test.go",
"mysql_filter_test.go",
"mysql_mask_test.go",
"mysql_report_test.go",
"mysql_subtitle_test.go",
"mysql_task_test.go",
"mysql_test.go",
"mysql_transfer_test.go",
"search_subtitle_test.go",
"search_test.go",
"task_test.go",
"videoup_test.go",
"workflow_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/dm/conf:go_default_library",
"//app/admin/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 = [
"account.go",
"bfs.go",
"credit.go",
"dao.go",
"mask.go",
"mc_filter.go",
"mc_subtitle.go",
"message.go",
"mysql.go",
"mysql_advance.go",
"mysql_filter.go",
"mysql_mask.go",
"mysql_report.go",
"mysql_subtitle.go",
"mysql_task.go",
"mysql_transfer.go",
"search.go",
"search_subtitle.go",
"task.go",
"videoup.go",
"workflow.go",
],
importpath = "go-common/app/admin/main/dm/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/dm/conf:go_default_library",
"//app/admin/main/dm/model:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/database/bfs:go_default_library",
"//library/database/elastic:go_default_library",
"//library/database/sql:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/metadata:go_default_library",
"//library/queue/databus: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",
"//app/admin/main/dm/dao/oplog:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,136 @@
package dao
import (
"context"
"fmt"
"math"
"net/url"
"time"
"go-common/app/admin/main/dm/model"
"go-common/library/log"
)
const (
_addMoral = "/api/moral/add"
_blockUser = "/x/internal/block/block"
_blockInfoAdd = "/x/internal/credit/blocked/info/add"
_blockArea = "2"
_blockSource = "1"
_blockForever = "2"
_blockTimeLimit = "1"
)
// ReduceMoral change moral
func (d *Dao) ReduceMoral(c context.Context, moral *model.ReduceMoral) (err error) {
var (
res = &struct {
Code int64 `json:"code"`
Morals map[int64]float64 `json:"morals"`
}{}
)
params := url.Values{}
params.Set("mid", fmt.Sprint(moral.UID))
params.Set("addMoral", fmt.Sprint(-math.Abs(float64(moral.Moral))))
params.Set("origin", "2")
params.Set("reason", model.AdminRptReason[moral.Reason])
params.Set("reason_type", "1")
params.Set("operater", moral.Operator)
params.Set("is_notify", fmt.Sprint(moral.IsNotify))
params.Set("remark", moral.Remark)
err = d.httpCli.Get(c, d.addMoralURI, "", params, res)
if err != nil {
log.Error("d.httpCli.Get(%s) error(%v)", d.addMoralURI+"?"+params.Encode(), err)
return
}
if res.Code != 0 {
err = fmt.Errorf("return code:%d", res.Code)
log.Error("d.httpCli.Get(%s) error(%v)", d.addMoralURI+"?"+params.Encode(), err)
}
return
}
// BlockUser block user
func (d *Dao) BlockUser(c context.Context, blu *model.BlockUser) (err error) {
if err = d.blockUser(c, blu); err != nil {
return
}
if err = d.blockInfoAdd(c, blu); err != nil {
return
}
return
}
func (d *Dao) blockUser(c context.Context, blu *model.BlockUser) (err error) {
var (
res = new(struct {
Code int `json:"data"`
})
params = url.Values{}
)
params.Set("mid", fmt.Sprint(blu.UID))
params.Set("source", _blockSource)
params.Set("area", _blockArea)
if blu.BlockForever == 1 {
params.Set("action", _blockForever)
} else {
params.Set("action", _blockTimeLimit)
}
params.Set("duration", fmt.Sprint(blu.BlockTimeLength*24*3600))
params.Set("start_time", fmt.Sprint(time.Now().Unix()))
params.Set("operator", blu.Operator)
params.Set("reason", fmt.Sprint(blu.ReasonType))
params.Set("comment", blu.BlockRemark)
params.Set("notify", "0")
err = d.httpCli.Post(c, d.blockUserURI, "", params, res)
if err != nil {
log.Error("d.httpCli.Post(%s) error(%v)", d.blockUserURI+"?"+params.Encode(), err)
return
}
if res.Code != 0 {
err = fmt.Errorf("return code:%d", res.Code)
log.Error("d.httpCli.Post(%s) error(%v)", d.blockUserURI+"?"+params.Encode(), err)
}
return
}
func (d *Dao) blockInfoAdd(c context.Context, blu *model.BlockUser) (err error) {
var (
res = new(struct {
Code int `json:"data"`
})
params = url.Values{}
)
params.Set("mid", fmt.Sprint(blu.UID))
if blu.BlockForever == 1 {
params.Set("blocked_forever", "1")
params.Set("punish_type", "3")
} else {
params.Set("blocked_forever", "0")
params.Set("punish_type", "2")
if blu.BlockTimeLength == 0 {
params.Set("punish_type", "1")
}
}
params.Set("blocked_days", fmt.Sprint(blu.BlockTimeLength))
params.Set("blocked_remark", blu.BlockRemark)
params.Set("moral_num", fmt.Sprint(blu.Moral))
params.Set("origin_content", fmt.Sprint(blu.OriginContent))
params.Set("origin_title", fmt.Sprint(blu.OriginTitle))
params.Set("origin_type", fmt.Sprint(blu.OriginType))
params.Set("origin_url", fmt.Sprint(blu.OriginURL))
params.Set("punish_time", fmt.Sprint(time.Now().Unix()))
params.Set("reason_type", fmt.Sprint(blu.ReasonType))
params.Set("operator_name", blu.Operator)
err = d.httpCli.Post(c, d.blockInfoAddURI, "", params, res)
if err != nil {
log.Error("d.httpCli.Post(%s) error(%v)", d.blockInfoAddURI+"?"+params.Encode(), err)
return
}
if res.Code != 0 {
err = fmt.Errorf("return code:%d", res.Code)
log.Error("d.httpCli.Post(%s) error(%v)", d.blockInfoAddURI+"?"+params.Encode(), err)
}
return
}

View File

@@ -0,0 +1,69 @@
package dao
import (
"context"
"testing"
"go-common/app/admin/main/dm/model"
. "github.com/smartystreets/goconvey/convey"
)
func TestReduceMoral(t *testing.T) {
arg := &model.ReduceMoral{
UID: 150781,
Moral: -1,
Origin: 2,
Reason: 1,
ReasonType: 1,
Operator: "zhang",
IsNotify: 1,
Remark: "dm admin test",
}
Convey("", t, func() {
err := testDao.ReduceMoral(context.TODO(), arg)
So(err, ShouldBeNil)
})
}
func TestBlockUser1(t *testing.T) {
arg := &model.BlockUser{
UID: 150781,
BlockForever: 1,
BlockTimeLength: 0,
BlockRemark: model.BlockReason[5],
ReasonType: 5,
Operator: "zhang",
OriginType: 2,
Moral: 10,
OriginURL: "aaaaa",
OriginContent: "test delete1",
OriginTitle: "test title",
IsNotify: 0,
}
Convey("", t, func() {
err := testDao.BlockUser(context.TODO(), arg)
So(err, ShouldBeNil)
})
}
func TestBlockUser2(t *testing.T) {
arg := &model.BlockUser{
UID: 150781,
BlockForever: 0,
BlockTimeLength: 5,
BlockRemark: model.BlockReason[5],
ReasonType: 5,
Operator: "zhang",
OriginType: 2,
Moral: 10,
OriginURL: "aaaaa",
OriginContent: "test delete2",
OriginTitle: "test title",
IsNotify: 0,
}
Convey("", t, func() {
err := testDao.BlockUser(context.TODO(), arg)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,21 @@
package dao
import (
"context"
"go-common/library/database/bfs"
"go-common/library/log"
)
// Upload .
func (d *Dao) Upload(c context.Context, bucket, fileName, contentType string, file []byte) (err error) {
if _, err = d.bfsCli.Upload(c, &bfs.Request{
Bucket: bucket,
ContentType: contentType,
Filename: fileName,
File: file,
}); err != nil {
log.Error("Upload(err:%v)", err)
}
return
}

View File

@@ -0,0 +1,39 @@
package dao
import (
"context"
"encoding/json"
"fmt"
"net/url"
"go-common/app/admin/main/dm/model"
"go-common/library/log"
)
const (
_sendJudge = "/x/internal/credit/blocked/case/add"
)
// SendJudgement send to judgement
func (d *Dao) SendJudgement(c context.Context, judges []*model.ReportJudge) (err error) {
params := url.Values{}
ret := struct {
Code int64 `json:"code"`
Message string `json:"message"`
}{}
data, err := json.Marshal(judges)
if err != nil {
log.Error("send judgement params(%s) create error(%v)", data, err)
return
}
params.Set("data", string(data))
if err = d.httpCli.Post(c, d.sendJudgeURI, "", params, &ret); err != nil {
log.Error("send judgement request(data: %s) error(%v)", data, err)
return
}
if ret.Code != 0 {
err = fmt.Errorf("%v", ret)
log.Error("send judgement request(data: %s) error(%v)", data, err)
}
return
}

View File

@@ -0,0 +1 @@
package dao

View File

@@ -0,0 +1,117 @@
package dao
import (
"context"
"go-common/app/admin/main/dm/conf"
"go-common/app/admin/main/dm/model"
"go-common/library/cache/memcache"
"go-common/library/database/bfs"
"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"
)
// Dao dao layer.
type Dao struct {
actionPub *databus.Databus
// http
httpSearch *bm.Client
httpCli *bm.Client
// mysql
dmMetaWriter *sql.DB
dmMetaReader *sql.DB
biliDM *sql.DB
// memcache
filterMC *memcache.Pool
// subtitle mc
subtitleMC *memcache.Pool
// elastic client
esCli *elastic.Elastic
// bfs client
bfsCli *bfs.BFS
// http uri
sendNotifyURI string
addMoralURI string
blockUserURI string
blockInfoAddURI string
sendJudgeURI string
viewsURI string
typesURI string
seasonURI string
maskURI string
workFlowURI string
berserkerURI string
}
// New new a dao and return.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
actionPub: databus.New(c.ActionPub),
// mysql
dmMetaWriter: sql.NewMySQL(c.DB.DMMetaWriter),
dmMetaReader: sql.NewMySQL(c.DB.DMMetaReader),
biliDM: sql.NewMySQL(c.DB.DM),
// memcache
filterMC: memcache.NewPool(c.Memcache.Filter.Config),
subtitleMC: memcache.NewPool(c.Memcache.Subtitle.Config),
// elastic client
esCli: elastic.NewElastic(c.Elastic),
// http client
sendNotifyURI: c.Host.Message + _sendNotify,
addMoralURI: c.Host.Account + _addMoral,
blockUserURI: c.Host.API + _blockUser,
blockInfoAddURI: c.Host.API + _blockInfoAdd,
sendJudgeURI: c.Host.API + _sendJudge,
viewsURI: c.Host.Videoup + _views,
typesURI: c.Host.Videoup + _types,
seasonURI: c.Host.Season + _season,
maskURI: c.Host.Mask + _mask,
berserkerURI: c.Host.Berserker,
workFlowURI: c.Host.API + _workFlowAppealDelete,
httpCli: bm.NewClient(c.HTTPClient.ClientConfig),
httpSearch: bm.NewClient(c.HTTPSearch.ClientConfig),
bfsCli: bfs.New(c.BFS),
}
return
}
// SendAction send action to job.
func (d *Dao) SendAction(c context.Context, k string, action *model.Action) (err error) {
if err = d.actionPub.Send(c, k, action); err != nil {
log.Error("actionPub.Send(action:%s,data:%s) error(%v)", action.Action, action.Data, err)
} else {
log.Info("actionPub.Send(action:%s,data:%s) success", action.Action, action.Data)
}
return
}
//BeginBiliDMTrans begin a transsaction of biliDM
func (d *Dao) BeginBiliDMTrans(c context.Context) (*sql.Tx, error) {
return d.biliDM.Begin(c)
}
// Ping ping success.
func (d *Dao) Ping(c context.Context) (err error) {
if err = d.dmMetaWriter.Ping(c); err != nil {
log.Error("d.dmMetaWriter error(%v)", err)
return
}
if err = d.dmMetaReader.Ping(c); err != nil {
log.Error("d.dmMetaReader error(%v)", err)
return
}
if err = d.biliDM.Ping(c); err != nil {
log.Error("d.biliDM error(%v)", err)
}
// mc
filterMC := d.filterMC.Get(c)
defer filterMC.Close()
if err = filterMC.Set(&memcache.Item{Key: "ping", Value: []byte("pong"), Expiration: 0}); err != nil {
log.Error("filterMC.Set error(%v)", err)
return
}
return
}

View File

@@ -0,0 +1,32 @@
package dao
import (
"flag"
"os"
"testing"
"go-common/app/admin/main/dm/conf"
"go-common/library/log"
)
var testDao *Dao
func TestMain(m *testing.M) {
flag.Set("app_id", "main.community.dm-admin")
flag.Set("conf_token", "dk9fifw9DT7wyCyrdMF0Qw9pQqUnuyIS")
flag.Set("tree_id", "2293")
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,57 @@
package dao
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
"go-common/library/log"
)
const _mask = "/dl/api/masks/v1"
// GenerateMask ask AI to generate dm mask
func (d *Dao) GenerateMask(c context.Context, cid, mid int64, plat int8, force int8, aid int64, duration int64, typeID int32) (err error) {
var (
res struct {
Code int64 `json:"errcode"`
Message string `json:"errmsg"`
}
params = make(map[string]interface{})
)
params["cid"] = cid
params["mask_platform"] = plat
params["force"] = force
params["mid"] = mid
params["aid"] = aid
params["duration"] = duration
params["region_2"] = typeID
data, err := json.Marshal(params)
if err != nil {
log.Error("json.Marshal(%v) error(%v)", params, err)
return
}
reader := bytes.NewReader(data)
req, err := http.NewRequest("POST", d.maskURI, reader)
if err != nil {
log.Error("http.NewRequest error(%v)", err)
return
}
req.Header.Set("Content-Type", "application/json")
for i := 0; i < 3; i++ {
if err = d.httpCli.Do(c, req, &res); err != nil {
continue
}
if res.Code != 200 {
err = fmt.Errorf("uri:%s,code:%d", d.maskURI, res.Code)
continue
}
break
}
if err != nil {
log.Error("d.GenerateMask(cid:%d, plat:%d) error(%v)", cid, plat, err)
}
return
}

View File

@@ -0,0 +1,14 @@
package dao
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestGenerateMask(t *testing.T) {
Convey("Test generate mask", t, func() {
testDao.GenerateMask(context.TODO(), 32, 11, 1, 0, 0, 0, 0)
})
}

View File

@@ -0,0 +1,32 @@
package dao
import (
"context"
"go-common/library/cache/memcache"
"go-common/library/log"
"strconv"
)
const _prefixUpFilter = "filter_up_"
func keyUpFilter(mid, oid int64) string {
return _prefixUpFilter + strconv.FormatInt(mid, 10) + "_" + strconv.FormatInt(oid, 10)
}
// DelUpFilterCache delete up filters from cache.
func (d *Dao) DelUpFilterCache(c context.Context, mid, oid int64) (err error) {
key := keyUpFilter(mid, oid)
conn := d.filterMC.Get(c)
err = conn.Delete(key)
conn.Close()
if err != nil {
if err == memcache.ErrNotFound {
err = nil
} else {
log.Error("memcache.Delete(%s) error(%v)", key, err)
}
}
return
}

View File

@@ -0,0 +1,36 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaokeyUpFilter(t *testing.T) {
convey.Convey("keyUpFilter", t, func(ctx convey.C) {
var (
mid = int64(0)
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyUpFilter(mid, oid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoDelUpFilterCache(t *testing.T) {
convey.Convey("DelUpFilterCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.DelUpFilterCache(c, mid, oid)
})
})
}

View File

@@ -0,0 +1,100 @@
package dao
import (
"context"
"fmt"
"go-common/library/cache/memcache"
"go-common/library/log"
)
const (
_fmtSubtitle = "s_subtitle_%d_%d"
_fmtVideoSubtitle = "s_video_%d_%d"
_fmtSubtitleDraft = "s_draft_%v_%v_%v_%v"
_fmtSubtitleSubject = "s_subtitle_allow_%d"
)
func (d *Dao) subtitleKey(oid int64, subtitleID int64) string {
return fmt.Sprintf(_fmtSubtitle, oid, subtitleID)
}
func (d *Dao) subtitleVideoKey(oid int64, tp int32) string {
return fmt.Sprintf(_fmtVideoSubtitle, oid, tp)
}
func (d *Dao) subtitleDraftKey(oid int64, tp int32, mid int64, lan uint8) string {
return fmt.Sprintf(_fmtSubtitleDraft, oid, tp, mid, lan)
}
func (d *Dao) subtitleSubjectKey(aid int64) string {
return fmt.Sprintf(_fmtSubtitleSubject, aid)
}
// DelVideoSubtitleCache .
func (d *Dao) DelVideoSubtitleCache(c context.Context, oid int64, tp int32) (err error) {
var (
key = d.subtitleVideoKey(oid, tp)
conn = d.subtitleMC.Get(c)
)
defer conn.Close()
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
} else {
log.Error("memcache.Delete(%s) error(%v)", key, err)
}
}
return
}
// DelSubtitleDraftCache .
func (d *Dao) DelSubtitleDraftCache(c context.Context, oid int64, tp int32, mid int64, lan uint8) (err error) {
var (
key = d.subtitleDraftKey(oid, tp, mid, lan)
conn = d.subtitleMC.Get(c)
)
defer conn.Close()
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
} else {
log.Error("memcache.Delete(%s) error(%v)", key, err)
}
}
return
}
// DelSubtitleCache .
func (d *Dao) DelSubtitleCache(c context.Context, oid int64, subtitleID int64) (err error) {
var (
key = d.subtitleKey(oid, subtitleID)
conn = d.subtitleMC.Get(c)
)
defer conn.Close()
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
} else {
log.Error("memcache.Delete(%s) error(%v)", key, err)
}
}
return
}
// DelSubtitleSubjectCache .
func (d *Dao) DelSubtitleSubjectCache(c context.Context, aid int64) (err error) {
var (
key = d.subtitleSubjectKey(aid)
conn = d.subtitleMC.Get(c)
)
defer conn.Close()
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
} else {
log.Error("memcache.Delete(%s) error(%v)", key, err)
}
}
return
}

View File

@@ -0,0 +1,122 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaosubtitleKey(t *testing.T) {
convey.Convey("subtitleKey", t, func(ctx convey.C) {
var (
oid = int64(0)
subtitleID = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := testDao.subtitleKey(oid, subtitleID)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaosubtitleVideoKey(t *testing.T) {
convey.Convey("subtitleVideoKey", t, func(ctx convey.C) {
var (
oid = int64(0)
tp = int32(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := testDao.subtitleVideoKey(oid, tp)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaosubtitleDraftKey(t *testing.T) {
convey.Convey("subtitleDraftKey", t, func(ctx convey.C) {
var (
oid = int64(0)
tp = int32(0)
mid = int64(0)
lan = uint8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := testDao.subtitleDraftKey(oid, tp, mid, lan)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaosubtitleSubjectKey(t *testing.T) {
convey.Convey("subtitleSubjectKey", t, func(ctx convey.C) {
var (
aid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := testDao.subtitleSubjectKey(aid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoDelVideoSubtitleCache(t *testing.T) {
convey.Convey("DelVideoSubtitleCache", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
tp = int32(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.DelVideoSubtitleCache(c, oid, tp)
})
})
}
func TestDaoDelSubtitleDraftCache(t *testing.T) {
convey.Convey("DelSubtitleDraftCache", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
tp = int32(0)
mid = int64(0)
lan = uint8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.DelSubtitleDraftCache(c, oid, tp, mid, lan)
})
})
}
func TestDaoDelSubtitleCache(t *testing.T) {
convey.Convey("DelSubtitleCache", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
subtitleID = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.DelSubtitleCache(c, oid, subtitleID)
})
})
}
func TestDaoDelSubtitleSubjectCache(t *testing.T) {
convey.Convey("DelSubtitleSubjectCache", t, func(ctx convey.C) {
var (
c = context.Background()
aid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.DelSubtitleSubjectCache(c, aid)
})
})
}

View File

@@ -0,0 +1,181 @@
package dao
import (
"context"
"fmt"
"net/url"
"go-common/app/admin/main/dm/model"
"go-common/library/log"
)
const (
_sendNotify = "/api/notify/send.user.notify.do"
_msgReporterTitle = "举报处理结果通知"
_msgPosterTitle = "弹幕违规处理通知"
_msgReporterKey = "1_6_4"
_msgPosterKey = "1_6_5"
_msgSubtitleTitle = "字幕状态变更"
_msgSubtitleUpKey = "1_6_8"
_msgSubtitleUserKey = "1_6_7"
)
type msgReturn struct {
Code int64 `json:"code"`
Ts interface{} `json:"ts"`
Data *struct {
Mc string `json:"mc"`
DataType int8 `json:"data_type"`
TotalCount int64 `json:"total_count"`
ErrorCount int64 `json:"error_count"`
ErrorMids []int64 `json:"error_mid_list"`
} `json:"data"`
}
// SendMsgToReporter send message
func (d *Dao) SendMsgToReporter(c context.Context, rptMsg *model.ReportMsg) (err error) {
var (
res = &msgReturn{}
)
params := url.Values{}
params.Set("mc", _msgReporterKey)
params.Set("title", _msgReporterTitle)
params.Set("data_type", "4")
params.Set("context", d.createReportContent(rptMsg))
params.Set("mid_list", rptMsg.Uids)
err = d.httpCli.Post(c, d.sendNotifyURI, "", params, res)
if err != nil {
log.Error("d.httpCli.Post(%s) error(%v)", d.sendNotifyURI+"?"+params.Encode(), err)
return
}
if res.Code != 0 {
err = fmt.Errorf("return code:%d", res.Code)
log.Error("d.httpCli.Post(%s) error(%v)", d.sendNotifyURI+"?"+params.Encode(), err)
}
return
}
func (d *Dao) createReportContent(rptMsg *model.ReportMsg) (content string) {
if rptMsg.State == model.StatSecondAutoDelete ||
rptMsg.State == model.StatFirstDelete ||
rptMsg.State == model.StatSecondDelete {
if rptMsg.Block != 0 { // 如果未封禁
content = fmt.Sprintf(model.RptTemplate["del"], rptMsg.Title, rptMsg.Aid, rptMsg.Msg, ",该用户已被封禁", model.BlockReason[rptMsg.BlockReason])
} else {
content = fmt.Sprintf(model.RptTemplate["del"], rptMsg.Title, rptMsg.Aid, rptMsg.Msg, "", model.AdminRptReason[rptMsg.RptReason])
}
} else {
content = fmt.Sprintf(model.RptTemplate["ignore"], rptMsg.Title, rptMsg.Aid, rptMsg.Msg)
}
return
}
// SendMsgToPoster send message
func (d *Dao) SendMsgToPoster(c context.Context, rptMsg *model.ReportMsg) (err error) {
var (
res = &msgReturn{}
)
params := url.Values{}
params.Set("mc", _msgPosterKey)
params.Set("title", _msgPosterTitle)
params.Set("data_type", "4")
msgContent, err := d.createPosterContent(rptMsg)
if err != nil {
log.Error("d.SendMsgToPoster error(%v)", err)
return
}
params.Set("context", msgContent)
params.Set("mid_list", rptMsg.Uids)
err = d.httpCli.Post(c, d.sendNotifyURI, "", params, res)
if err != nil {
log.Error("d.httpCli.Post(%s) error(%v)", d.sendNotifyURI+"?"+params.Encode(), err)
return
}
if res.Code != 0 {
err = fmt.Errorf("return code:%d", res.Code)
log.Error("d.httpCli.Post(%s) error(%v)", d.sendNotifyURI+"?"+params.Encode(), err)
}
return
}
func (d *Dao) createPosterContent(rptMsg *model.ReportMsg) (content string, err error) {
var (
part1, part2, tmpl string
)
if rptMsg.Block > 0 {
part1 = fmt.Sprintf(",并被封禁%d天", rptMsg.Block)
part2 = model.BlockReason[rptMsg.BlockReason]
tmpl, err = model.PosterBlockMsg(rptMsg.BlockReason)
if err != nil {
log.Error("reportModel.PosterBlockMsg error(%v)", err)
return
}
content = fmt.Sprintf(tmpl, rptMsg.Title, rptMsg.Aid, rptMsg.Msg, part1, part2)
} else if rptMsg.Block == -1 {
part1 = ",并被永久封禁"
part2 = model.BlockReason[rptMsg.BlockReason]
tmpl, err = model.PosterBlockMsg(rptMsg.BlockReason)
if err != nil {
log.Error("reportModel.PosterBlockMsg error(%v)", err)
return
}
content = fmt.Sprintf(tmpl, rptMsg.Title, rptMsg.Aid, rptMsg.Msg, part1, part2)
} else {
part1 = ""
part2 = model.AdminRptReason[rptMsg.RptReason]
tmpl, err = model.PosterAdminRptMsg(rptMsg.RptReason)
if err != nil {
log.Error("report.PosterAdminRptMsg error(%v)", err)
return
}
content = fmt.Sprintf(tmpl, rptMsg.Title, rptMsg.Aid, rptMsg.Msg, part1, part2)
}
return
}
// SendMsgToSubtitleUp .
func (d *Dao) SendMsgToSubtitleUp(c context.Context, arg *model.NotifySubtitleUp) (err error) {
var (
res = &msgReturn{}
)
params := url.Values{}
params.Set("mc", _msgSubtitleUpKey)
params.Set("title", _msgSubtitleTitle)
params.Set("data_type", "4")
params.Set("context", arg.Msg())
params.Set("mid_list", fmt.Sprint(arg.Mid))
err = d.httpCli.Post(c, d.sendNotifyURI, "", params, res)
if err != nil {
log.Error("d.httpCli.Post(%s) error(%v)", d.sendNotifyURI+"?"+params.Encode(), err)
return
}
if res.Code != 0 {
err = fmt.Errorf("return code:%d", res.Code)
log.Error("d.httpCli.Post(%s) error(%v)", d.sendNotifyURI+"?"+params.Encode(), err)
}
return
}
// SendMsgToSubtitleUser .
func (d *Dao) SendMsgToSubtitleUser(c context.Context, arg *model.NotifySubtitleUser) (err error) {
var (
res = &msgReturn{}
)
params := url.Values{}
params.Set("mc", _msgSubtitleUserKey)
params.Set("title", _msgSubtitleTitle)
params.Set("data_type", "4")
params.Set("context", arg.Msg())
params.Set("mid_list", fmt.Sprint(arg.Mid))
err = d.httpCli.Post(c, d.sendNotifyURI, "", params, res)
if err != nil {
log.Error("d.httpCli.Post(%s) error(%v)", d.sendNotifyURI+"?"+params.Encode(), err)
return
}
if res.Code != 0 {
err = fmt.Errorf("return code:%d", res.Code)
log.Error("d.httpCli.Post(%s) error(%v)", d.sendNotifyURI+"?"+params.Encode(), err)
}
return
}

View File

@@ -0,0 +1,170 @@
package dao
import (
"testing"
"go-common/app/admin/main/dm/model"
. "github.com/smartystreets/goconvey/convey"
)
//func TestDao_SendMsgToReporter1(t *testing.T) {
// var (
// d = New(conf.Conf)
// c = context.TODO()
// err error
// rptMsg = &model.ReportMsg{
// Aid: 1,
// Title: "test title1",
// Did: 1,
// Msg: "dm msg1",
// Uids: "150781",
// State: model.StatFirstDelete,
// RptReason: 1,
// BlockReason: 1,
// Block: -1,
// }
// )
// err = d.SendMsgToReporter(c, rptMsg)
// if err != nil {
// t.Errorf("dao.SendMsgToReporter(rptMsg:%v) err(%v)", rptMsg, err)
// t.Fail()
// }
//}
//
//func TestDao_SendMsgToReporter2(t *testing.T) {
// var (
// d = New(conf.Conf)
// c = context.TODO()
// err error
// rptMsg = &model.ReportMsg{
// Aid: 1,
// Title: "test title2",
// Did: 1,
// Msg: "dm msg2",
// Uids: "150781",
// State: model.StatSecondDelete,
// RptReason: 3,
// BlockReason: 5,
// Block: -1,
// }
// )
// err = d.SendMsgToReporter(c, rptMsg)
// if err != nil {
// t.Errorf("dao.SendMsgToReporter(rptMsg:%v) err(%v)", rptMsg, err)
// t.Fail()
// }
//}
//
//func TestDao_SendMsgToReporter3(t *testing.T) {
// var (
// d = New(conf.Conf)
// c = context.TODO()
// err error
// rptMsg = &model.ReportMsg{
// Aid: 1,
// Title: "test title3",
// Did: 1,
// Msg: "dm msg3",
// Uids: "150781",
// State: model.StatFirstIgnore,
// RptReason: 1,
// BlockReason: 1,
// Block: -1,
// }
// )
// err = d.SendMsgToReporter(c, rptMsg)
// if err != nil {
// t.Errorf("dao.SendMsgToReporter(rptMsg:%v) err(%v)", rptMsg, err)
// t.Fail()
// }
//}
//
//func TestDao_SendMsgToReporter4(t *testing.T) {
// var (
// d = New(conf.Conf)
// c = context.TODO()
// err error
// rptMsg = &model.ReportMsg{
// Aid: 1,
// Title: "test title4",
// Did: 1,
// Msg: "dm msg4",
// Uids: "150781",
// State: model.StatSecondIgnore,
// RptReason: 1,
// BlockReason: 1,
// Block: -1,
// }
// )
// err = d.SendMsgToReporter(c, rptMsg)
// if err != nil {
// t.Errorf("dao.SendMsgToReporter(rptMsg:%v) err(%v)", rptMsg, err)
// t.Fail()
// }
//}
//
//func TestDao_SendMsgToReporter5(t *testing.T) {
// var (
// d = New(conf.Conf)
// c = context.TODO()
// err error
// rptMsg = &model.ReportMsg{
// Aid: 1,
// Title: "test title5",
// Did: 1,
// Msg: "dm msg5",
// Uids: "150781",
// State: model.StatSecondAutoDelete,
// RptReason: 1,
// BlockReason: 5,
// Block: -1,
// }
// )
// err = d.SendMsgToReporter(c, rptMsg)
// if err != nil {
// t.Errorf("dao.SendMsgToReporter(rptMsg:%v) err(%v)", rptMsg, err)
// t.Fail()
// }
//}
//
//func TestDao_SendMsgToPoster1(t *testing.T) {
// var (
// d = New(conf.Conf)
// c = context.TODO()
// err error
// rptMsg = &model.ReportMsg{
// Aid: 1,
// Title: "test title1",
// Did: 1,
// Msg: "dm msg1",
// Uids: "150781",
// State: model.StatSecondAutoDelete,
// RptReason: 1,
// BlockReason: 5,
// Block: 10,
// }
// )
// err = d.SendMsgToPoster(c, rptMsg)
// if err != nil {
// t.Errorf("dao.SendMsgToPoster(rptMsg:%v) err(%v)", rptMsg, err)
// t.Fail()
// }
//}
func TestCreatePosterContent(t *testing.T) {
msg := &model.ReportMsg{
Aid: 1,
Uids: "1,2",
Did: 11,
Title: "test title",
Msg: "test dm content",
State: 1,
RptReason: 16,
Block: 0,
BlockReason: 0,
}
Convey("test poster content", t, func() {
_, err := testDao.createPosterContent(msg)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,323 @@
package dao
import (
"context"
"fmt"
"sync"
"go-common/app/admin/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
// subject
_updateSubAttr = "UPDATE dm_subject_%02d SET attr=? WHERE type=? AND oid=?"
_updateSubCount = "UPDATE dm_subject_%02d SET acount=?,count=? WHERE type=? AND oid=?"
_updateSubMCountSQL = "UPDATE dm_subject_%02d SET mcount=? WHERE type=? AND oid=?"
_incrSubMoveCntSQL = "UPDATE dm_subject_%02d SET move_count=move_count+? WHERE type=? AND oid=?"
_updateSubPoolSQL = "UPDATE dm_subject_%02d SET childpool=? WHERE type=? AND oid=?"
_updateSubStateSQL = "UPDATE dm_subject_%02d SET state=? WHERE type=? AND oid=?"
_updateSubMaxlimitSQL = "UPDATE dm_subject_%02d SET maxlimit=? WHERE type=? AND oid=?"
_incrSubCountSQL = "UPDATE dm_subject_%02d SET count=count+? WHERE type=? AND oid=?"
_selectDMCount = "SELECT count(*) from dm_index_%03d WHERE type=? AND oid=? AND state IN(%s)"
_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=?"
_getSubjectsSQL = "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 IN(%s)"
_contentsSQL = "SELECT dmid,fontsize,color,mode,ip,plat,msg,ctime,mtime FROM dm_content_%03d WHERE dmid IN(%s)"
_contentsSpeSQL = "SELECT dmid,msg,ctime,mtime FROM dm_special_content WHERE dmid IN(%s)"
_idxsByidSQL = "SELECT id,type,oid,mid,progress,state,pool,attr,ctime,mtime FROM dm_index_%03d WHERE type=? AND oid=? AND id IN(%s)"
_updatePoolID = "UPDATE dm_index_%03d SET pool=? WHERE type=? AND id IN (%s)"
_updateDMState = "UPDATE dm_index_%03d SET state=? WHERE type=? AND id IN (%s)"
_updateDMAttr = "UPDATE dm_index_%03d SET attr=? WHERE type=? 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(oid int64) int64 {
return oid % _contentSharding
}
// UpSubjectAttr update subject attr.
func (d *Dao) UpSubjectAttr(c context.Context, tp int32, oid int64, attr int32) (affect int64, err error) {
res, err := d.dmMetaWriter.Exec(c, fmt.Sprintf(_updateSubAttr, d.hitSubject(oid)), attr, tp, oid)
if err != nil {
log.Error("dmMetaWriter.Exec() error(%v)", err)
return
}
return res.RowsAffected()
}
// UpSubjectCount update acount,count of subject.
func (d *Dao) UpSubjectCount(c context.Context, tp int32, oid, acount, count int64) (affect int64, err error) {
res, err := d.dmMetaWriter.Exec(c, fmt.Sprintf(_updateSubCount, d.hitSubject(oid)), acount, count, tp, oid)
if err != nil {
log.Error("dmMetaWriter.Exec() error(%v)", err)
return
}
return res.RowsAffected()
}
// IncrSubjectCount update count.
func (d *Dao) IncrSubjectCount(c context.Context, tp int32, oid, count int64) (affect int64, err error) {
res, err := d.dmMetaWriter.Exec(c, fmt.Sprintf(_incrSubCountSQL, d.hitSubject(oid)), count, tp, oid)
if err != nil {
log.Error("dmMetaWriter.Exec() error(%v)", err)
return
}
return res.RowsAffected()
}
// UpSubjectMCount update monitor dm count.
func (d *Dao) UpSubjectMCount(c context.Context, tp int32, oid, cnt int64) (affect int64, err error) {
res, err := d.dmMetaWriter.Exec(c, fmt.Sprintf(_updateSubMCountSQL, d.hitSubject(oid)), cnt, tp, oid)
if err != nil {
log.Error("d.dmMetaWriter.Exect(%s,%d,%d,%d) error(%v)", _updateSubMCountSQL, cnt, tp, oid, err)
return
}
return res.RowsAffected()
}
// IncrSubMoveCount update move_count in dm_subject.
func (d *Dao) IncrSubMoveCount(c context.Context, tp int32, oid, count int64) (affect int64, err error) {
res, err := d.dmMetaWriter.Exec(c, fmt.Sprintf(_incrSubMoveCntSQL, d.hitSubject(oid)), count, tp, oid)
if err != nil {
log.Error("d.dmMetaWriter.Exec(%s,%d,%d,%d) error(%v)", _incrSubMoveCntSQL, tp, oid, count, err)
return
}
return res.RowsAffected()
}
// UpSubjectPool update childpool in dm subject.
func (d *Dao) UpSubjectPool(c context.Context, tp int32, oid int64, childpool int32) (affect int64, err error) {
res, err := d.dmMetaWriter.Exec(c, fmt.Sprintf(_updateSubPoolSQL, d.hitSubject(oid)), childpool, tp, oid)
if err != nil {
log.Error("d.dmWriter.Exect(%s,%d,%d,%d) error(%v)", _updateSubPoolSQL, childpool, tp, oid, err)
return
}
return res.RowsAffected()
}
// UpSubjectState update state in dm subject.
func (d *Dao) UpSubjectState(c context.Context, tp int32, oid int64, state int32) (affect int64, err error) {
res, err := d.dmMetaWriter.Exec(c, fmt.Sprintf(_updateSubStateSQL, d.hitSubject(oid)), state, tp, oid)
if err != nil {
log.Error("d.dmWriter.Exect(%s,%d,%d,%d) error(%v)", _updateSubStateSQL, state, tp, oid, err)
return
}
return res.RowsAffected()
}
// UpSubjectMaxlimit update maxlimit in dm subject.
func (d *Dao) UpSubjectMaxlimit(c context.Context, tp int32, oid, maxlimit int64) (affect int64, err error) {
res, err := d.dmMetaWriter.Exec(c, fmt.Sprintf(_updateSubMaxlimitSQL, d.hitSubject(oid)), maxlimit, tp, oid)
if err != nil {
log.Error("d.dmWriter.Exect(%s,%d,%d,%d) error(%v)", _updateSubMaxlimitSQL, maxlimit, tp, oid, err)
return
}
return res.RowsAffected()
}
// DMCount statistics dm count by dm state.
func (d *Dao) DMCount(c context.Context, tp int32, oid int64, states []int64) (count int64, err error) {
row := d.dmMetaReader.QueryRow(c, fmt.Sprintf(_selectDMCount, d.hitIndex(oid), xstr.JoinInts(states)), tp, oid)
if err = row.Scan(&count); err != nil {
log.Error("row.Scan() error(%v)", err)
}
return
}
// 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
}
// Subjects multi get subjects.
func (d *Dao) Subjects(c context.Context, tp int32, oids []int64) (res map[int64]*model.Subject, err error) {
var (
oidMap = make(map[int64][]int64)
mutext = &sync.Mutex{}
wg, errCtx = errgroup.WithContext(c)
)
if len(oids) == 0 {
return
}
res = make(map[int64]*model.Subject, len(oids))
for _, oid := range oids {
if _, ok := oidMap[d.hitSubject(oid)]; !ok {
oidMap[d.hitSubject(oid)] = make([]int64, 0)
}
oidMap[d.hitSubject(oid)] = append(oidMap[d.hitSubject(oid)], oid)
}
for key, value := range oidMap {
k := key
v := value
wg.Go(func() (err error) {
rows, err := d.dmMetaReader.Query(errCtx, fmt.Sprintf(_getSubjectsSQL, k, xstr.JoinInts(v)), tp)
if err != nil {
log.Error("dmMetaReader.Query() error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
s := &model.Subject{}
err = rows.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)
if err != nil {
log.Error("rows.Scan() error(%v)", err)
return
}
mutext.Lock()
res[s.Oid] = s
mutext.Unlock()
}
return
})
}
if err = wg.Wait(); err != nil {
log.Error("d.Subjects() error(%v)", err)
return
}
if len(res) == 0 {
res = nil
}
return
}
// SetStateByIDs change danmu state in new db
func (d *Dao) SetStateByIDs(c context.Context, tp int32, oid int64, ids []int64, state int32) (affect int64, err error) {
sqlStr := fmt.Sprintf(_updateDMState, d.hitIndex(oid), xstr.JoinInts(ids))
res, err := d.dmMetaWriter.Exec(c, sqlStr, state, tp)
if err != nil {
log.Error("d.dmMetaWriter.Exec(%s %d) error(%v)", sqlStr, state, err)
return
}
return res.RowsAffected()
}
// SetAttrByIDs set attr by mult dmids in new db
func (d *Dao) SetAttrByIDs(c context.Context, tp int32, oid int64, ids []int64, val int32) (affect int64, err error) {
sqlStr := fmt.Sprintf(_updateDMAttr, d.hitIndex(oid), xstr.JoinInts(ids))
res, err := d.dmMetaWriter.Exec(c, sqlStr, val, tp)
if err != nil {
log.Error("d.dmMetaWriter.Exec(%s %d) error(%v)", sqlStr, val, err)
return
}
return res.RowsAffected()
}
// SetPoolIDByIDs change danmu poolid
func (d *Dao) SetPoolIDByIDs(c context.Context, tp int32, oid int64, pool int32, dmids []int64) (affect int64, err error) {
sqlStr := fmt.Sprintf(_updatePoolID, d.hitIndex(oid), xstr.JoinInts(dmids))
res, err := d.dmMetaWriter.Exec(c, sqlStr, pool, tp)
if err != nil {
log.Error("d.dbComment.Exec(%v) error(%v)", sqlStr, err)
return
}
return res.RowsAffected()
}
// IndexsByID get dm index by dmids.
func (d *Dao) IndexsByID(c context.Context, tp int32, oid int64, dmids []int64) (idxMap map[int64]*model.DM, special []int64, err error) {
query := fmt.Sprintf(_idxsByidSQL, d.hitIndex(oid), xstr.JoinInts(dmids))
rows, err := d.dmMetaReader.Query(c, query, tp, oid)
if err != nil {
log.Error("db.Query() error(%v)", err)
return
}
defer rows.Close()
idxMap = make(map[int64]*model.DM, len(dmids))
for rows.Next() {
idx := new(model.DM)
if err = rows.Scan(&idx.ID, &idx.Type, &idx.Oid, &idx.Mid, &idx.Progress, &idx.State, &idx.Pool, &idx.Attr, &idx.Ctime, &idx.Mtime); err != nil {
log.Error("row.Scan() error(%v)", err)
return
}
idxMap[idx.ID] = idx
if idx.Pool == model.PoolSpecial {
special = append(special, idx.ID)
}
}
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()
}
return
})
}
err = wg.Wait()
return
}
// SpecialContents multi get special dm content by dmids.
func (d *Dao) SpecialContents(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
}
return
}

View File

@@ -0,0 +1,85 @@
package dao
import (
"context"
"go-common/app/admin/main/dm/model"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
_countAdvsSQLAll = "SELECT count(*) FROM dm_advancecomment WHERE dm_inid=? "
_countAdvsSQLMode = "SELECT count(*) FROM dm_advancecomment WHERE dm_inid=? AND mode=? "
_countAdvsSQLType = "SELECT count(*) FROM dm_advancecomment WHERE dm_inid=? AND type=? "
_countAdvsSQLTypeMode = "SELECT count(*) FROM dm_advancecomment WHERE dm_inid=? AND type=? AND mode=? "
_selAdvsSQLAll = "SELECT buy_id,type,mode,mid,timestamp FROM dm_advancecomment WHERE dm_inid=? ORDER BY buy_id DESC limit ?,?"
_selAdvsSQLMode = "SELECT buy_id,type,mode,mid,timestamp FROM dm_advancecomment WHERE dm_inid=? AND mode=? ORDER BY buy_id DESC limit ?,?"
_selAdvsSQLType = "SELECT buy_id,type,mode,mid,timestamp FROM dm_advancecomment WHERE dm_inid=? AND type=? ORDER BY buy_id DESC limit ?,?"
_selAdvsSQLTypeMode = "SELECT buy_id,type,mode,mid,timestamp FROM dm_advancecomment WHERE dm_inid=? AND type=? AND mode=? ORDER BY buy_id DESC ?,?"
)
// Advances 获取高级弹幕申请
func (d *Dao) Advances(c context.Context, dmInid int64, typ, mode string, pn, ps int64) (res []*model.Advance, total int64, err error) {
var rows *sql.Rows
res = make([]*model.Advance, 0)
if typ == model.AdvTypeAll {
if mode == model.AdvModeAll {
countRow := d.biliDM.QueryRow(c, _countAdvsSQLAll, dmInid)
if err = countRow.Scan(&total); err != nil {
log.Error("row.ScanCount error(%v)", err)
return
}
rows, err = d.biliDM.Query(c, _selAdvsSQLAll, dmInid, (pn-1)*ps, ps)
if err != nil {
log.Error("d.dbDM.Query(%s,%d,%d,%d) error(%v)", _selAdvsSQLAll, dmInid, (pn-1)*ps, ps, err)
return
}
} else {
countRow := d.biliDM.QueryRow(c, _countAdvsSQLMode, dmInid, mode)
if err = countRow.Scan(&total); err != nil {
log.Error("row.ScanCount error(%v)", err)
return
}
rows, err = d.biliDM.Query(c, _selAdvsSQLMode, dmInid, mode, (pn-1)*ps, ps)
if err != nil {
log.Error("d.dbDM.Query(%s,%d,%s,%d,%d) error(%v)", _selAdvsSQLMode, dmInid, mode, (pn-1)*ps, ps, err)
return
}
}
} else {
if mode == model.AdvModeAll {
countRow := d.biliDM.QueryRow(c, _countAdvsSQLType, dmInid, typ)
if err = countRow.Scan(&total); err != nil {
log.Error("row.ScanCount error(%v)", err)
return
}
rows, err = d.biliDM.Query(c, _selAdvsSQLType, dmInid, typ, (pn-1)*ps, ps)
if err != nil {
log.Error("d.dbDM.Query(%s,%d,%s,%d,%d) error(%v)", _selAdvsSQLType, dmInid, typ, (pn-1)*ps, ps, err)
return
}
} else {
countRow := d.biliDM.QueryRow(c, _countAdvsSQLTypeMode, dmInid, typ)
if err = countRow.Scan(&total); err != nil {
log.Error("row.ScanCount error(%v)", err)
return
}
rows, err = d.biliDM.Query(c, _selAdvsSQLTypeMode, dmInid, typ, mode, (pn-1)*ps, ps)
if err != nil {
log.Error("d.dbDM.Query(%s,%d,%s,%s,%d,%d) error(%v)", _selAdvsSQLTypeMode, dmInid, typ, mode, (pn-1)*ps, ps, err)
return
}
}
}
defer rows.Close()
for rows.Next() {
adv := &model.Advance{}
if err = rows.Scan(&adv.ID, &adv.Type, &adv.Mode, &adv.Mid, &adv.Timestamp); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
res = append(res, adv)
}
return
}

View File

@@ -0,0 +1,13 @@
package dao
import (
"context"
"testing"
)
func TestAdvances(t *testing.T) {
_, _, err := testDao.Advances(context.TODO(), 27515260, "all", "all", 1, 20)
if err != nil {
t.Error(err)
}
}

View File

@@ -0,0 +1,94 @@
package dao
import (
"context"
"fmt"
"go-common/app/admin/main/dm/model"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
_upFilterSharding = 10
_countUpFiltersSQL = "SELECT count(*) FROM dm_filter_up_%02d WHERE mid=? AND type=? AND active=1"
_countUpFiltersAllSQL = "SELECT count(*) FROM dm_filter_up_%02d WHERE mid=? AND active=1"
_getUpFiltersSQL = "SELECT id,oid,type,filter,ctime FROM dm_filter_up_%02d WHERE mid=? AND type=? AND active=1 ORDER BY id DESC limit ?,?"
_getUpFiltersAllSQL = "SELECT id,oid,type,filter,ctime FROM dm_filter_up_%02d WHERE mid=? AND active=1 ORDER BY id DESC limit ?,?"
_uptUpFilterSQL = "UPDATE dm_filter_up_%02d SET active=? WHERE id=?"
_updateUpFilterCntSQL = "UPDATE dm_filter_up_count SET count=count+? WHERE mid=? AND type=? AND count<?"
)
func (d *Dao) hitUpFilter(mid int64) int64 {
return mid % _upFilterSharding
}
// UpFilters return filter rules according type
func (d *Dao) UpFilters(c context.Context, mid, tp, pn, ps int64) (res []*model.UpFilter, total int64, err error) {
res = make([]*model.UpFilter, 0)
countRow := d.biliDM.QueryRow(c, fmt.Sprintf(_countUpFiltersSQL, d.hitUpFilter(mid)), mid, tp)
if err = countRow.Scan(&total); err != nil {
log.Error("row.ScanCount error(%v)", err)
return
}
rows, err := d.biliDM.Query(c, fmt.Sprintf(_getUpFiltersSQL, d.hitUpFilter(mid)), mid, tp, (pn-1)*ps, ps)
if err != nil {
log.Error("dbDM.Query(mid:%d, oid:%d) error(%v)", mid, tp, err)
return
}
defer rows.Close()
for rows.Next() {
f := &model.UpFilter{}
if err = rows.Scan(&f.ID, &f.Oid, &f.Type, &f.Filter, &f.Ctime); err != nil {
log.Error("rows.Scan() error(%v)", err)
return
}
res = append(res, f)
}
return
}
// UpFiltersAll return all filter rules
func (d *Dao) UpFiltersAll(c context.Context, mid, pn, ps int64) (res []*model.UpFilter, total int64, err error) {
res = make([]*model.UpFilter, 0)
countRow := d.biliDM.QueryRow(c, fmt.Sprintf(_countUpFiltersAllSQL, d.hitUpFilter(mid)), mid)
if err = countRow.Scan(&total); err != nil {
log.Error("row.ScanCount error(%v)", err)
return
}
rows, err := d.biliDM.Query(c, fmt.Sprintf(_getUpFiltersAllSQL, d.hitUpFilter(mid)), mid, (pn-1)*ps, ps)
if err != nil {
log.Error("dbDM.Query(mid:%d) error(%v)", mid, err)
return
}
defer rows.Close()
for rows.Next() {
f := &model.UpFilter{}
if err = rows.Scan(&f.ID, &f.Oid, &f.Type, &f.Filter, &f.Ctime); err != nil {
log.Error("rows.Scan() error(%v)", err)
return
}
res = append(res, f)
}
return
}
// UpdateUpFilter batch edit filter.
func (d *Dao) UpdateUpFilter(tx *sql.Tx, mid, id int64, active int8) (affect int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_uptUpFilterSQL, d.hitUpFilter(mid)), active, id)
if err != nil {
log.Error("tx.Exec(mid:%d,id:%d,active:%d) error(%v)", mid, id, active, err)
return
}
return res.RowsAffected()
}
// UpdateUpFilterCnt set count
func (d *Dao) UpdateUpFilterCnt(tx *sql.Tx, mid int64, ftype int8, count, limit int) (affect int64, err error) {
res, err := tx.Exec(_updateUpFilterCntSQL, count, mid, ftype, limit)
if err != nil {
log.Error("d.UpdateUpFilterCnt(mid:%d, type:%d, count:%d) error(%v)", mid, ftype, count, err)
return
}
return res.RowsAffected()
}

View File

@@ -0,0 +1,25 @@
package dao
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestMultiAddUpFilters(t *testing.T) {
Convey("", t, func() {
tx, err := testDao.BeginBiliDMTrans(context.TODO())
So(err, ShouldBeNil)
So(tx, ShouldNotBeNil)
Convey("", func() {
_, err := testDao.UpdateUpFilter(tx, 16299551, 33, 0)
So(err, ShouldBeNil)
if err != nil {
_, err = testDao.UpdateUpFilterCnt(tx, 162, 1, 1, 1000)
So(err, ShouldBeNil)
}
tx.Commit()
})
})
}

View File

@@ -0,0 +1,52 @@
package dao
import (
"context"
"go-common/app/admin/main/dm/model"
"go-common/library/log"
)
const (
_countMaskUp = "SELECT count(*) FROM dm_mask_up WHERE state=1"
_getMaskUp = "SELECT id,mid,state,comment,ctime,mtime from dm_mask_up where state=1 ORDER BY mtime DESC limit ?,? "
_maskUpOpen = "INSERT INTO dm_mask_up(mid,state,comment) VALUES (?,?,?) ON DUPLICATE KEY UPDATE state=?,comment=?"
)
// MaskUps get mask up info from db.
func (d *Dao) MaskUps(c context.Context, pn, ps int64) (maskUps []*model.MaskUp, total int64, err error) {
maskUps = make([]*model.MaskUp, 0)
countRow := d.biliDM.QueryRow(c, _countMaskUp)
if err = countRow.Scan(&total); err != nil {
log.Error("row.ScanCount error(%v)", err)
return
}
rows, err := d.biliDM.Query(c, _getMaskUp, (pn-1)*ps, ps)
if err != nil {
log.Error("biliDM.Query(%s) error(%v)", _getMaskUp, err)
return
}
defer rows.Close()
for rows.Next() {
maskUp := &model.MaskUp{}
if err = rows.Scan(&maskUp.ID, &maskUp.Mid, &maskUp.State, &maskUp.Comment, &maskUp.CTime, &maskUp.MTime); err != nil {
log.Error("biliDM.Scan(%s) error(%v)", _getMaskUp, err)
return
}
maskUps = append(maskUps, maskUp)
}
if err = rows.Err(); err != nil {
log.Error("biliDM.rows.Err() error(%v)", err)
}
return
}
// MaskUpOpen mask up open.
func (d *Dao) MaskUpOpen(c context.Context, mid int64, state int32, comment string) (affect int64, err error) {
res, err := d.biliDM.Exec(c, _maskUpOpen, mid, state, comment, state, comment)
if err != nil {
log.Error("d.biliDM.Exec(%s,%d,%v,%v) error(%v)", _maskUpOpen, mid, state, comment, err)
return
}
return res.RowsAffected()
}

View File

@@ -0,0 +1,27 @@
package dao
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestMaskUps(t *testing.T) {
Convey("test mask ups", t, func() {
res, total, err := testDao.MaskUps(context.Background(), 1, 50)
So(err, ShouldBeNil)
So(res, ShouldNotBeEmpty)
So(total, ShouldNotBeNil)
t.Log(res, total)
})
}
func TestMaskUpOpen(t *testing.T) {
Convey("test mask up open", t, func() {
res, err := testDao.MaskUpOpen(context.Background(), 27515266, 1, "")
So(err, ShouldBeNil)
So(res, ShouldNotBeEmpty)
t.Log(res)
})
}

View File

@@ -0,0 +1,153 @@
package dao
import (
"bytes"
"context"
"fmt"
"go-common/app/admin/main/dm/model"
"go-common/library/log"
"go-common/library/xstr"
)
const (
_userSharding = 100
_logSharding = 100
_reportSharding = 100
// dm report
_updateStatSQL = "UPDATE dm_report_%d SET state=? WHERE dmid IN (%s)"
_ignoreStatSQL = "UPDATE dm_report_%d SET state=?,count=0 WHERE dmid IN (%s)"
_selectRpt = "SELECT id,dmid,cid,uid,reason,count,up_op,state,score,rp_time,ctime,mtime FROM dm_report_%d WHERE dmid IN (%s)"
_selectUsers = "SELECT id,dmid,uid,reason,state,ctime,mtime FROM dm_report_user_%d WHERE dmid IN (%s) AND state=? ORDER BY id"
_updateUser = "UPDATE dm_report_user_%d SET state=? WHERE dmid IN (%s) AND state !=?"
_insertLog = "INSERT dm_report_admin_log_%d (dmid,adminid,reason,result,remark,elapsed) VALUES"
_selectLog = "SELECT id,dmid,adminid,reason,result,remark,elapsed,ctime,mtime FROM dm_report_admin_log_%d WHERE dmid=? ORDER BY mtime"
)
// RptTable return report table id by cid
func RptTable(cid int64) int64 {
return cid % _reportSharding
}
// UserTable return user table id by dmid
func UserTable(dmid int64) int64 {
return dmid % _userSharding
}
// LogTable return log table id by dmid
func LogTable(dmid int64) int64 {
return dmid % _logSharding
}
// ChangeReportStat change report state
func (d *Dao) ChangeReportStat(c context.Context, cid int64, dmids []int64, state int8) (err error) {
updateSQL := fmt.Sprintf(_updateStatSQL, RptTable(cid), xstr.JoinInts(dmids))
if _, err = d.biliDM.Exec(c, updateSQL, state); err != nil {
log.Error("d.biliDM.Exec(%d) error(%v)", state, err)
}
return
}
// IgnoreReport change report state to SecondIgnore or FirstIngnore
func (d *Dao) IgnoreReport(c context.Context, cid int64, dmids []int64, state int8) (err error) {
updateSQL := fmt.Sprintf(_ignoreStatSQL, RptTable(cid), xstr.JoinInts(dmids))
if _, err = d.biliDM.Exec(c, updateSQL, state); err != nil {
log.Error("d.biliDM.Exec(%d) error(%v)", state, err)
}
return
}
// Reports get multi dm report info.
func (d *Dao) Reports(c context.Context, cid int64, dmids []int64) (res []*model.Report, err error) {
res = []*model.Report{}
selectSQL := fmt.Sprintf(_selectRpt, RptTable(cid), xstr.JoinInts(dmids))
rows, err := d.biliDM.Query(c, selectSQL)
if err != nil {
log.Error("d.biliDM.Exec(cid:%d,dmids:%v) error(%v)", cid, dmids, err)
return
}
defer rows.Close()
for rows.Next() {
r := &model.Report{}
err = rows.Scan(&r.ID, &r.Did, &r.Cid, &r.UID, &r.RpType, &r.Count, &r.UpOP, &r.State, &r.Score, &r.RpTime, &r.Ctime, &r.Mtime)
if err != nil {
log.Error("rows.Scan() error(%v)", err)
return
}
res = append(res, r)
}
return
}
// ReportUsers get user list.
func (d *Dao) ReportUsers(c context.Context, tableID int64, dmids []int64, state int8) (res map[int64][]*model.ReportUser, err error) {
res = make(map[int64][]*model.ReportUser, 100)
selectSQL := fmt.Sprintf(_selectUsers, tableID, xstr.JoinInts(dmids))
rows, err := d.biliDM.Query(c, selectSQL, state)
if err != nil {
log.Error("d.biliDM.Query(sql:%s) error(%v)", selectSQL, err)
return
}
defer rows.Close()
for rows.Next() {
u := &model.ReportUser{}
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
}
res[u.Did] = append(res[u.Did], u)
}
return
}
// UpReportUserState update report user state.
func (d *Dao) UpReportUserState(c context.Context, tableID int64, dmids []int64, state int8) (affect int64, err error) {
selectSQL := fmt.Sprintf(_updateUser, tableID, xstr.JoinInts(dmids))
res, err := d.biliDM.Exec(c, selectSQL, state, state)
if err != nil {
log.Error("d.updateUserStmt.Exec(dmid:%v) error(%v)", dmids, err)
return
}
return res.RowsAffected()
}
// AddReportLog add dm report admin log.
func (d *Dao) AddReportLog(c context.Context, tableID int64, lg []*model.ReportLog) (err error) {
var (
buffer bytes.Buffer
insertTp string
)
insertTp = "(%d,%d,%d,%d,'%s',%d),"
buffer.WriteString(fmt.Sprintf(_insertLog, tableID))
for _, v := range lg {
buffer.WriteString(fmt.Sprintf(insertTp, v.Did, v.AdminID, v.Reason, v.Result, v.Remark, v.Elapsed))
}
//truncate the last ','
buffer.Truncate(buffer.Len() - 1)
_, err = d.biliDM.Exec(c, buffer.String())
if err != nil {
log.Error("d.insertLogStmt.Exec(%v) error(%v)", lg, err)
return
}
return
}
// ReportLog get dm report log.
func (d *Dao) ReportLog(c context.Context, dmid int64) (res []*model.ReportLog, err error) {
selectSQL := fmt.Sprintf(_selectLog, LogTable(dmid))
rows, err := d.biliDM.Query(c, selectSQL, dmid)
if err != nil {
log.Error("dmreport:d.biliDM.Query(sql:%s) error(%v)", selectSQL, err)
return
}
defer rows.Close()
for rows.Next() {
r := &model.ReportLog{}
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)
}
return
}

View File

@@ -0,0 +1,149 @@
package dao
import (
"context"
"go-common/app/admin/main/dm/model"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoRptTable(t *testing.T) {
convey.Convey("RptTable", t, func(ctx convey.C) {
var (
cid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := RptTable(cid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoUserTable(t *testing.T) {
convey.Convey("UserTable", t, func(ctx convey.C) {
var (
dmid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := UserTable(dmid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoLogTable(t *testing.T) {
convey.Convey("LogTable", t, func(ctx convey.C) {
var (
dmid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := LogTable(dmid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoChangeReportStat(t *testing.T) {
convey.Convey("ChangeReportStat", t, func(ctx convey.C) {
var (
c = context.Background()
cid = int64(0)
dmids = []int64{}
state = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.ChangeReportStat(c, cid, dmids, state)
})
})
}
func TestDaoIgnoreReport(t *testing.T) {
convey.Convey("IgnoreReport", t, func(ctx convey.C) {
var (
c = context.Background()
cid = int64(0)
dmids = []int64{}
state = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.IgnoreReport(c, cid, dmids, state)
})
})
}
func TestDaoReports(t *testing.T) {
convey.Convey("Reports", t, func(ctx convey.C) {
var (
c = context.Background()
cid = int64(0)
dmids = []int64{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.Reports(c, cid, dmids)
})
})
}
func TestDaoReportUsers(t *testing.T) {
convey.Convey("ReportUsers", t, func(ctx convey.C) {
var (
c = context.Background()
tableID = int64(0)
dmids = []int64{}
state = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.ReportUsers(c, tableID, dmids, state)
})
})
}
func TestDaoUpReportUserState(t *testing.T) {
convey.Convey("UpReportUserState", t, func(ctx convey.C) {
var (
c = context.Background()
tableID = int64(0)
dmids = []int64{}
state = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.UpReportUserState(c, tableID, dmids, state)
})
})
}
func TestDaoAddReportLog(t *testing.T) {
convey.Convey("AddReportLog", t, func(ctx convey.C) {
var (
c = context.Background()
tableID = int64(0)
lg = []*model.ReportLog{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.AddReportLog(c, tableID, lg)
})
})
}
func TestDaoReportLog(t *testing.T) {
convey.Convey("ReportLog", t, func(ctx convey.C) {
var (
c = context.Background()
dmid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := testDao.ReportLog(c, dmid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,182 @@
package dao
import (
"context"
"fmt"
"time"
"go-common/app/admin/main/dm/model"
"go-common/library/database/sql"
"go-common/library/log"
"go-common/library/xstr"
)
const (
_subtitleSharding = 100
_getSubtitles = "SELECT id,oid,type,lan,aid,mid,author_mid,up_mid,is_sign,is_lock,status,subtitle_url,pub_time,mtime FROM subtitle_%02d WHERE id in (%s)"
_getSubtitle = "SELECT id,oid,type,lan,aid,mid,author_mid,up_mid,is_sign,is_lock,status,subtitle_url,pub_time,mtime FROM subtitle_%02d WHERE id=?"
_countSubtitleDraft = "SELECT COUNT(id) FROM subtitle_%02d WHERE oid=? AND type=? AND lan=? AND mid=? AND pub_time=0"
_updateSubtitle = "UPDATE subtitle_%02d set status=?,pub_time=? where id=?"
_getSubtitlePubID = "SELECT id FROM subtitle_%02d WHERE oid=? AND type=? AND lan=? AND status=5 ORDER BY pub_time DESC limit 1"
_addSubtitlePub = "INSERT INTO subtitle_pub(oid,type,lan,subtitle_id,is_delete) VALUES(?,?,?,?,?) ON DUPLICATE KEY UPDATE subtitle_id=?,is_delete=?"
_getSubtitleLans = "SELECT code,lan,doc_zh FROM subtitle_language WHERE is_delete=0"
_addSubtitleSubject = "INSERT INTO subtitle_subject(aid,allow,attr,lan_code) VALUES(?,?,?,?) ON DUPLICATE KEY UPDATE allow=?,attr=?,lan_code=?"
_getSubtitleSubject = "SELECT aid,allow,attr,lan_code from subtitle_subject WHERE aid=?"
)
func (d *Dao) hitSubtitle(oid int64) int64 {
return oid % _subtitleSharding
}
// GetSubtitles .
func (d *Dao) GetSubtitles(c context.Context, oid int64, subtitleIds []int64) (subtitles []*model.Subtitle, err error) {
rows, err := d.biliDM.Query(c, fmt.Sprintf(_getSubtitles, d.hitSubtitle(oid), xstr.JoinInts(subtitleIds)))
if err != nil {
log.Error("params(subtitleIds:%v),error(%v)", subtitleIds, err)
return
}
defer rows.Close()
for rows.Next() {
subtitle := &model.Subtitle{}
var t time.Time
if err = rows.Scan(&subtitle.ID, &subtitle.Oid, &subtitle.Type, &subtitle.Lan, &subtitle.Aid, &subtitle.Mid, &subtitle.AuthorID, &subtitle.UpMid, &subtitle.IsSign, &subtitle.IsLock, &subtitle.Status, &subtitle.SubtitleURL, &subtitle.PubTime, &t); err != nil {
log.Error("params(subtitleIds:%v),error(%v)", subtitleIds, err)
return
}
subtitle.Mtime = t.Unix()
subtitles = append(subtitles, subtitle)
}
if err = rows.Err(); err != nil {
log.Error("params(subtitleIds:%v),error(%v)", subtitleIds, err)
return
}
return
}
// GetSubtitle .
func (d *Dao) GetSubtitle(c context.Context, oid, subtitleID int64) (subtitle *model.Subtitle, err error) {
row := d.biliDM.QueryRow(c, fmt.Sprintf(_getSubtitle, d.hitSubtitle(oid)), subtitleID)
subtitle = &model.Subtitle{}
var t time.Time
if err = row.Scan(&subtitle.ID, &subtitle.Oid, &subtitle.Type, &subtitle.Lan, &subtitle.Aid, &subtitle.Mid, &subtitle.AuthorID, &subtitle.UpMid, &subtitle.IsSign, &subtitle.IsLock, &subtitle.Status, &subtitle.SubtitleURL, &subtitle.PubTime, &t); err != nil {
if err == sql.ErrNoRows {
err = nil
subtitle = nil
return
}
log.Error("params(subtitleIds:%v),error(%v)", subtitleID, err)
return
}
subtitle.Mtime = t.Unix()
return
}
// UpdateSubtitle .
func (d *Dao) UpdateSubtitle(c context.Context, subtitle *model.Subtitle) (err error) {
if _, err = d.biliDM.Exec(c, fmt.Sprintf(_updateSubtitle, d.hitSubtitle(subtitle.Oid)), subtitle.Status, subtitle.PubTime, subtitle.ID); err != nil {
log.Error("UpdateSubtitle.params(subtitle:%+v),error(%v)", subtitle, err)
return
}
return
}
// CountSubtitleDraft .
func (d *Dao) CountSubtitleDraft(c context.Context, oid int64, mid int64, lan uint8, tp int32) (count int64, err error) {
row := d.biliDM.QueryRow(c, fmt.Sprintf(_countSubtitleDraft, d.hitSubtitle(oid)), oid, tp, lan, mid)
if err = row.Scan(&count); err != nil {
if err == sql.ErrNoRows {
err = nil
count = 0
return
}
log.Error("params(oid:%v, tp:%v, mid:%v, lan:%v),error(%v)", oid, tp, mid, lan, err)
return
}
return
}
// TxUpdateSubtitle .
func (d *Dao) TxUpdateSubtitle(tx *sql.Tx, subtitle *model.Subtitle) (err error) {
if _, err = tx.Exec(fmt.Sprintf(_updateSubtitle, d.hitSubtitle(subtitle.Oid)), subtitle.Status, subtitle.PubTime, subtitle.ID); err != nil {
log.Error("TxUpdateSubtitle.params(subtitle:%+v),error(%v)", subtitle, err)
return
}
return
}
// TxGetSubtitleID .
func (d *Dao) TxGetSubtitleID(tx *sql.Tx, oid int64, tp int32, lan uint8) (subtitleID int64, err error) {
row := tx.QueryRow(fmt.Sprintf(_getSubtitlePubID, d.hitSubtitle(oid)), oid, tp, lan)
if err = row.Scan(&subtitleID); err != nil {
if err == sql.ErrNoRows {
err = nil
subtitleID = 0
return
}
log.Error("TxGetSubtitleID.Scac(err:%v)", err)
return
}
return
}
// TxUpdateSubtitlePub .
func (d *Dao) TxUpdateSubtitlePub(tx *sql.Tx, subtitlePub *model.SubtitlePub) (err error) {
if _, err = tx.Exec(_addSubtitlePub, subtitlePub.Oid, subtitlePub.Type, subtitlePub.Lan, subtitlePub.SubtitleID, subtitlePub.IsDelete, subtitlePub.SubtitleID, subtitlePub.IsDelete); err != nil {
log.Error("params(%+v),error(%v)", subtitlePub, err)
return
}
return
}
// SubtitleLans .
func (d *Dao) SubtitleLans(c context.Context) (subtitleLans []*model.SubtitleLan, err error) {
rows, err := d.biliDM.Query(c, _getSubtitleLans)
if err != nil {
log.Error("params(query:%v),error(%v)", _getSubtitleLans, err)
return
}
defer rows.Close()
for rows.Next() {
subtitleLan := new(model.SubtitleLan)
if err = rows.Scan(&subtitleLan.Code, &subtitleLan.Lan, &subtitleLan.DocZh); err != nil {
log.Error("params.Sacn(query:%v),error(%v)", _getSubtitleLans, err)
return
}
subtitleLans = append(subtitleLans, subtitleLan)
}
if err = rows.Err(); err != nil {
log.Error("params.Err(query:%v),error(%v)", _getSubtitleLans, err)
return
}
return
}
// AddSubtitleSubject .
func (d *Dao) AddSubtitleSubject(c context.Context, subtitleSubject *model.SubtitleSubject) (err error) {
if _, err = d.biliDM.Exec(c, _addSubtitleSubject, subtitleSubject.Aid, subtitleSubject.Allow, subtitleSubject.Attr, subtitleSubject.Lan, subtitleSubject.Allow, subtitleSubject.Attr, subtitleSubject.Lan); err != nil {
log.Error("params(subtitleSubject:%+v),error(%v)", subtitleSubject, err)
return
}
return
}
// GetSubtitleSubject .
func (d *Dao) GetSubtitleSubject(c context.Context, aid int64) (subtitleSubject *model.SubtitleSubject, err error) {
subtitleSubject = new(model.SubtitleSubject)
row := d.biliDM.QueryRow(c, _getSubtitleSubject, aid)
if err = row.Scan(&subtitleSubject.Aid, &subtitleSubject.Allow, &subtitleSubject.Attr, &subtitleSubject.Lan); err != nil {
if err == sql.ErrNoRows {
err = nil
subtitleSubject = nil
return
}
log.Error("params(aid:%v),error(%v)", aid, err)
return
}
return
}

View File

@@ -0,0 +1,177 @@
package dao
import (
"context"
"go-common/app/admin/main/dm/model"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaohitSubtitle(t *testing.T) {
convey.Convey("hitSubtitle", t, func(ctx convey.C) {
var (
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := testDao.hitSubtitle(oid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoGetSubtitles(t *testing.T) {
convey.Convey("GetSubtitles", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
subtitleIds = []int64{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.GetSubtitles(c, oid, subtitleIds)
})
})
}
func TestDaoGetSubtitle(t *testing.T) {
convey.Convey("GetSubtitle", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
subtitleID = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.GetSubtitle(c, oid, subtitleID)
})
})
}
func TestDaoUpdateSubtitle(t *testing.T) {
convey.Convey("UpdateSubtitle", t, func(ctx convey.C) {
var (
c = context.Background()
subtitle = &model.Subtitle{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.UpdateSubtitle(c, subtitle)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoCountSubtitleDraft(t *testing.T) {
convey.Convey("CountSubtitleDraft", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
mid = int64(0)
lan = uint8(0)
tp = int32(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
count, err := testDao.CountSubtitleDraft(c, oid, mid, lan, tp)
ctx.Convey("Then err should be nil.count should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(count, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoTxUpdateSubtitle(t *testing.T) {
convey.Convey("TxUpdateSubtitle", t, func(ctx convey.C) {
var (
tx, _ = testDao.BeginBiliDMTrans(context.TODO())
subtitle = &model.Subtitle{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.TxUpdateSubtitle(tx, subtitle)
})
ctx.Reset(func() {
tx.Commit()
})
})
}
func TestDaoTxGetSubtitleID(t *testing.T) {
convey.Convey("TxGetSubtitleID", t, func(ctx convey.C) {
var (
tx, _ = testDao.BeginBiliDMTrans(context.TODO())
oid = int64(0)
tp = int32(0)
lan = uint8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.TxGetSubtitleID(tx, oid, tp, lan)
})
ctx.Reset(func() {
tx.Commit()
})
})
}
func TestDaoTxUpdateSubtitlePub(t *testing.T) {
convey.Convey("TxUpdateSubtitlePub", t, func(ctx convey.C) {
var (
tx, _ = testDao.BeginBiliDMTrans(context.TODO())
subtitlePub = &model.SubtitlePub{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.TxUpdateSubtitlePub(tx, subtitlePub)
})
ctx.Reset(func() {
tx.Commit()
})
})
}
func TestDaoSubtitleLans(t *testing.T) {
convey.Convey("SubtitleLans", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
subtitleLans, err := testDao.SubtitleLans(c)
ctx.Convey("Then err should be nil.subtitleLans should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(subtitleLans, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoAddSubtitleSubject(t *testing.T) {
convey.Convey("AddSubtitleSubject", t, func(ctx convey.C) {
var (
c = context.Background()
subtitleSubject = &model.SubtitleSubject{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.AddSubtitleSubject(c, subtitleSubject)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoGetSubtitleSubject(t *testing.T) {
convey.Convey("GetSubtitleSubject", t, func(ctx convey.C) {
var (
c = context.Background()
aid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
subtitleSubject, err := testDao.GetSubtitleSubject(c, aid)
ctx.Convey("Then err should be nil.subtitleSubject should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(subtitleSubject, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,166 @@
package dao
import (
"context"
"fmt"
"strings"
"time"
"go-common/app/admin/main/dm/model"
"go-common/library/database/sql"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_countDMTask = "SELECT count(*) FROM dm_task"
_selectDMTask = "SELECT id,title,creator,reviewer,state,result,ctime,mtime FROM dm_task%s order by ctime limit ?,? "
_insertDMTask = "INSERT INTO dm_task(title,creator,regex,keywords,ips,mids,cids,start,end,state,sub) VALUES(?,?,?,?,?,?,?,?,?,?,?)"
_insertDMSubTask = "INSERT INTO dm_sub_task(task_id,operation,start,rate) VALUES(?,?,?,?)"
_updateDMTaskState = "UPDATE dm_task SET state=? WHERE id IN (%s) AND state!=?"
_reviewDmTask = "UPDATE dm_task SET state=?,reviewer=?,topic=? WHERE id=? AND state=0"
_selectTaskByID = "SELECT id,title,creator,reviewer,regex,keywords,ips,mids,cids,start,end,qcount,state,result,ctime,mtime FROM dm_task WHERE id=?"
_selectSubTask = "SELECT id,operation,rate,tcount,start,end FROM dm_sub_task WHERE task_id=?"
_editTaskPriority = "UPDATE dm_task SET priority=? WHERE id IN (%s)"
)
// TaskList dm task list
func (d *Dao) TaskList(c context.Context, taskSQL []string, pn, ps int64) (tasks []*model.TaskInfo, total int64, err error) {
var sql string
tasks = make([]*model.TaskInfo, 0)
if len(taskSQL) > 0 {
sql = fmt.Sprintf(" WHERE %s", strings.Join(taskSQL, " AND "))
}
countRow := d.biliDM.QueryRow(c, _countDMTask+sql)
if err = countRow.Scan(&total); err != nil {
log.Error("row.ScanCount(%s) error(%v)", _countDMTask+sql, err)
return
}
rows, err := d.biliDM.Query(c, fmt.Sprintf(_selectDMTask, sql), (pn-1)*ps, ps)
if err != nil {
log.Error("biliDM.Query(%s) error(%v)", fmt.Sprintf(_selectDMTask, sql), err)
return
}
defer rows.Close()
for rows.Next() {
task := &model.TaskInfo{}
var cTime, mTime time.Time
if err = rows.Scan(&task.ID, &task.Title, &task.Creator, &task.Reviewer, &task.State, &task.Result, &cTime, &mTime); err != nil {
log.Error("biliDM.Scan(%s) error(%v)", fmt.Sprintf(_selectDMTask, sql), err)
return
}
task.Ctime = cTime.Format("2006-01-02 15:04:05")
task.Mtime = mTime.Format("2006-01-02 15:04:05")
tasks = append(tasks, task)
}
if err = rows.Err(); err != nil {
log.Error("biliDM.rows.Err() error(%v)", err)
}
return
}
// AddTask add dm task
func (d *Dao) AddTask(tx *sql.Tx, v *model.AddTaskArg, sub int32) (taskID int64, err error) {
var sTime, eTime time.Time
if sTime, err = time.ParseInLocation("2006-01-02 15:04:05", v.Start, time.Local); err != nil {
log.Error("d.AddTask time.Parse(%s) error(%v)", v.Start, err)
return
}
if eTime, err = time.ParseInLocation("2006-01-02 15:04:05", v.End, time.Local); err != nil {
log.Error("d.AddTask time.Parse(%s) error(%v)", v.End, err)
return
}
// regex add slash
rows, err := tx.Exec(_insertDMTask, v.Title, v.Creator, v.Regex, v.KeyWords, v.IPs, v.Mids, v.Cids, sTime, eTime, v.State, sub)
if err != nil {
log.Error("tx.Exec(%s params:%+v) error(%v)", _insertDMTask, v, err)
return
}
return rows.LastInsertId()
}
// AddSubTask add dm sub task
func (d *Dao) AddSubTask(tx *sql.Tx, taskID int64, operation int32, start string, rate int32) (id int64, err error) {
sTime, err := time.ParseInLocation("2006-01-02 15:04:05", start, time.Local)
if err != nil {
log.Error("d.AddSubTask time.Parse(%s) error(%v)", start, err)
return
}
rows, err := tx.Exec(_insertDMSubTask, taskID, operation, sTime, rate)
if err != nil {
log.Error("tx.Exec(%s,%d,%d,%s,%d) error(%v)", _insertDMSubTask, taskID, operation, start, rate, err)
return
}
return rows.LastInsertId()
}
// EditTaskState .
func (d *Dao) EditTaskState(c context.Context, v *model.EditTasksStateArg) (affected int64, err error) {
updateSQL := fmt.Sprintf(_updateDMTaskState, v.IDs)
rows, err := d.biliDM.Exec(c, updateSQL, v.State, v.State)
if err != nil {
log.Error("d.EditTaskState.Exec(id:%s, state:%d) error(%v)", v.IDs, v.State, err)
return
}
return rows.RowsAffected()
}
// EditTaskPriority .
func (d *Dao) EditTaskPriority(c context.Context, ids string, priority int64) (affected int64, err error) {
updateSQL := fmt.Sprintf(_editTaskPriority, ids)
rows, err := d.biliDM.Exec(c, updateSQL, priority)
if err != nil {
log.Error("d.EditTaskPriority.Exec(ids:%s, priority:%d) error(%v)", ids, priority, err)
return
}
return rows.RowsAffected()
}
// ReviewTask .
func (d *Dao) ReviewTask(c context.Context, v *model.ReviewTaskArg) (affected int64, err error) {
row, err := d.biliDM.Exec(c, _reviewDmTask, v.State, v.Reviewer, v.Topic, v.ID)
if err != nil {
log.Error("d.ReviewTask.Exec(id:%d, state:%d) error(%v)", v.ID, v.State, err)
return
}
return row.RowsAffected()
}
// TaskView .
func (d *Dao) TaskView(c context.Context, id int64) (task *model.TaskView, err error) {
task = new(model.TaskView)
row := d.biliDM.QueryRow(c, _selectTaskByID, id)
var sTime, eTime, cTime, mTime time.Time
if err = row.Scan(&task.ID, &task.Title, &task.Creator, &task.Reviewer, &task.Regex, &task.KeyWords, &task.IPs, &task.Mids, &task.Cids, &sTime, &eTime, &task.QCount, &task.State, &task.Result, &cTime, &mTime); err != nil {
if err == sql.ErrNoRows {
err = ecode.NothingFound
}
log.Error("biliDM.Scan(%s, id:%d) error(%v)", _selectTaskByID, id, err)
return
}
task.Start = sTime.Format("2006-01-02 15:04:05")
task.End = eTime.Format("2006-01-02 15:04:05")
task.Ctime = cTime.Format("2006-01-02 15:04:05")
task.Mtime = mTime.Format("2006-01-02 15:04:05")
return
}
// SubTask .
func (d *Dao) SubTask(c context.Context, id int64) (subTask *model.SubTask, err error) {
// TODO: operation time
subTask = new(model.SubTask)
row := d.biliDM.QueryRow(c, _selectSubTask, id)
var sTime time.Time
var eTime time.Time
if err = row.Scan(&subTask.ID, &subTask.Operation, &subTask.Rate, &subTask.Tcount, &sTime, &eTime); err != nil {
if err == sql.ErrNoRows {
err = nil
subTask = nil
}
log.Error("biliDM.Scan(%s, taskID:%d) error*(%v)", _selectSubTask, id, err)
return
}
subTask.Start = sTime.Format("2006-01-02 15:04:05")
subTask.End = eTime.Format("2006-01-02 15:04:05")
return
}

View File

@@ -0,0 +1,159 @@
package dao
import (
"context"
"testing"
"go-common/app/admin/main/dm/model"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoTaskList(t *testing.T) {
convey.Convey("TaskList", t, func(ctx convey.C) {
var (
c = context.Background()
taskSQL = []string{}
pn = int64(1)
ps = int64(50)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
tasks, total, err := testDao.TaskList(c, taskSQL, pn, ps)
ctx.Convey("Then err should be nil.tasks,total should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(total, convey.ShouldNotBeNil)
t.Logf("====%d", total)
ctx.So(tasks, convey.ShouldNotBeNil)
// t.Logf("====%+v", tasks[0])
})
})
})
}
func TestDaoAddTask(t *testing.T) {
convey.Convey("AddTask", t, func(ctx convey.C) {
var (
tx, _ = testDao.BeginBiliDMTrans(context.Background())
v = &model.AddTaskArg{
Title: "test",
Start: "2016-10-30 16:12:21",
End: "2018-10-30 16:12:21",
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
taskID, err := testDao.AddTask(tx, v, 1)
ctx.Convey("Then err should be nil.taskID should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(taskID, convey.ShouldNotBeNil)
t.Logf("====%d", taskID)
tx.Commit()
})
})
})
}
func TestDaoAddSubTask(t *testing.T) {
convey.Convey("AddSubTask", t, func(ctx convey.C) {
var (
tx, _ = testDao.BeginBiliDMTrans(context.Background())
taskID = int64(8)
operation = int32(0)
start = "2018-10-30 16:12:21"
rate = int32(100)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
id, err := testDao.AddSubTask(tx, taskID, operation, start, rate)
ctx.Convey("Then err should be nil.id should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(id, convey.ShouldNotBeNil)
t.Logf("====%d", id)
})
tx.Commit()
})
})
}
func TestDaoEditTaskState(t *testing.T) {
convey.Convey("EditTaskState", t, func(ctx convey.C) {
var (
c = context.Background()
v = &model.EditTasksStateArg{
IDs: "1,7",
State: 1,
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
affected, err := testDao.EditTaskState(c, v)
ctx.Convey("Then err should be nil.affected should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affected, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoTaskView(t *testing.T) {
convey.Convey("TaskView", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(1)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
task, err := testDao.TaskView(c, id)
ctx.Convey("Then err should be nil.task should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(task, convey.ShouldNotBeNil)
t.Logf("====%+v", task)
})
})
})
}
func TestDaoSubTask(t *testing.T) {
convey.Convey("SubTask", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(8)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
subTask, err := testDao.SubTask(c, id)
ctx.Convey("Then err should be nil.subTask should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(subTask, convey.ShouldNotBeNil)
t.Logf("====%+v", subTask)
})
})
})
}
func TestDaoReviewTask(t *testing.T) {
convey.Convey("ReviewTask", t, func(ctx convey.C) {
var (
c = context.Background()
v = &model.ReviewTaskArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
affected, err := testDao.ReviewTask(c, v)
ctx.Convey("Then err should be nil.affected should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affected, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoEditTaskPriority(t *testing.T) {
convey.Convey("EditTaskPriority", t, func(ctx convey.C) {
var (
c = context.Background()
ids = "12"
priority = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
affected, err := testDao.EditTaskPriority(c, ids, priority)
ctx.Convey("Then err should be nil.affected should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affected, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,183 @@
package dao
import (
"context"
"testing"
"go-common/app/admin/main/dm/model"
. "github.com/smartystreets/goconvey/convey"
)
func TestUpSubjectAttr(t *testing.T) {
Convey("test update subject attr", t, func() {
_, err := testDao.UpSubjectAttr(context.TODO(), 1, 1221, 16)
So(err, ShouldBeNil)
})
}
func TestUpSubjectCount(t *testing.T) {
Convey("update count in subject", t, func() {
_, err := testDao.UpSubjectCount(context.TODO(), 1, 1221, 1, 1)
So(err, ShouldBeNil)
})
}
func TestIncrSubjectCount(t *testing.T) {
Convey("update count in subject", t, func() {
_, err := testDao.IncrSubjectCount(context.TODO(), 1, 1221, 1)
So(err, ShouldBeNil)
})
}
func TestIncrSubMoveCount(t *testing.T) {
Convey("update move count in subject", t, func() {
_, err := testDao.IncrSubMoveCount(context.TODO(), 1, 1221, 1)
So(err, ShouldBeNil)
})
}
func TestIncrSubCount(t *testing.T) {
Convey("update count in subject", t, func() {
_, err := testDao.IncrSubjectCount(context.TODO(), 1, 1221, 1)
So(err, ShouldBeNil)
})
}
func TestUpSubjectPool(t *testing.T) {
Convey("update childpool in subject", t, func() {
_, err := testDao.UpSubjectPool(context.TODO(), 1, 1221, 1)
So(err, ShouldBeNil)
})
}
func TestUpSubjectState(t *testing.T) {
Convey("update state in subject", t, func() {
_, err := testDao.UpSubjectState(context.TODO(), 1, 1221, 1)
So(err, ShouldBeNil)
})
}
func TestUpSubjectMaxlimit(t *testing.T) {
Convey("update maxlimit in subject", t, func() {
_, err := testDao.UpSubjectMaxlimit(context.TODO(), 1, 1221, 8000)
So(err, ShouldBeNil)
})
}
func TestSubject(t *testing.T) {
var (
tp int32 = 1
oid int64 = 1508
c = context.TODO()
)
Convey("subject test", t, func() {
_, err := testDao.Subject(c, tp, oid)
So(err, ShouldBeNil)
})
}
func TestSubjects(t *testing.T) {
oids := []int64{1221, 1321}
Convey("subject test", t, func() {
res, err := testDao.Subjects(context.TODO(), 1, oids)
So(err, ShouldBeNil)
So(res, ShouldNotBeEmpty)
})
}
func TestChangeReportStat(t *testing.T) {
var (
c = context.TODO()
cid int64 = 1
dmids = []int64{1, 2, 3, 4, 5}
state = model.StatFirstDelete
)
Convey("update dm report state and err shoule be nil", t, func() {
err := testDao.ChangeReportStat(c, cid, dmids, state)
So(err, ShouldBeNil)
})
}
func TestIgnoreReport(t *testing.T) {
var (
cid int64 = 1
c = context.TODO()
dmids = []int64{1, 2, 3, 4, 5}
state int8 = 4
)
Convey("ignore dm report state and err shoule be nil", t, func() {
err := testDao.IgnoreReport(c, cid, dmids, state)
So(err, ShouldBeNil)
})
}
func TestReports(t *testing.T) {
var (
cid int64 = 10109027
c = context.TODO()
dmids = []int64{719218595}
)
Convey("", t, func() {
res, err := testDao.Reports(c, cid, dmids)
So(err, ShouldBeNil)
So(res, ShouldNotBeEmpty)
for _, r := range res {
t.Logf("===:%+v", r)
}
})
}
func TestReportUsers(t *testing.T) {
var (
tableID int64 = 1
c = context.TODO()
state = model.NoticeUnsend
dmids = []int64{1, 2, 3, 4, 5}
)
Convey("", t, func() {
_, err := testDao.ReportUsers(c, tableID, dmids, state)
So(err, ShouldBeNil)
})
}
func TestUpReportUserState(t *testing.T) {
var (
tableID int64 = 1
c = context.TODO()
state = model.NoticeSend
dmids = []int64{1, 2, 3, 4, 5}
)
Convey("", t, func() {
_, err := testDao.UpReportUserState(c, tableID, dmids, state)
So(err, ShouldBeNil)
})
}
func TestAddReportLog(t *testing.T) {
var (
tableID int64 = 1
c = context.TODO()
lg = &model.ReportLog{
ID: 1,
Did: 1234,
AdminID: 1,
}
)
Convey("", t, func() {
err := testDao.AddReportLog(c, tableID, []*model.ReportLog{lg})
So(err, ShouldBeNil)
})
}
func TestReportLog(t *testing.T) {
var (
dmid int64 = 719918888
c = context.TODO()
)
Convey("", t, func() {
res, err := testDao.ReportLog(c, dmid)
So(err, ShouldBeNil)
So(res, ShouldNotBeEmpty)
})
}

View File

@@ -0,0 +1,93 @@
package dao
import (
"context"
"go-common/app/admin/main/dm/model"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
_InstTrJobSQL = "INSERT INTO dm_transfer_job(from_cid,to_cid,mid,offset,state) VALUES(?,?,?,?,?)"
_countTransList = "SELECT count(*) FROM dm_transfer_job WHERE to_cid=?"
_countTransListState = "SELECT count(*) FROM dm_transfer_job WHERE to_cid=? AND state=?"
_TransList = "SELECT id,from_cid,to_cid,state,ctime FROM dm_transfer_job WHERE to_cid=? limit ?,?"
_TransListState = "SELECT id,from_cid,to_cid,state,ctime FROM dm_transfer_job WHERE to_cid=? AND state=? limit ?, ?"
_selTransferID = "SELECT id,from_cid,to_cid,mid,offset,state,ctime,mtime from dm_transfer_job WHERE id=?"
_uptTransferSQL = "UPDATE dm_transfer_job SET state=? WHERE id=?"
)
// InsertTransferJob add transfer job
func (d *Dao) InsertTransferJob(c context.Context, from, to, mid int64, offset float64, state int8) (affect int64, err error) {
row, err := d.biliDM.Exec(c, _InstTrJobSQL, from, to, mid, offset, state)
if err != nil {
log.Error("biliDM.Exec(%s, %d %d %d %v) error(%v)", _InstTrJobSQL, from, to, mid, offset, err)
return
}
return row.LastInsertId()
}
// TransferList transfer list
func (d *Dao) TransferList(c context.Context, cid, state, pn, ps int64) (res []*model.TransList, total int64, err error) {
var rows *sql.Rows
res = make([]*model.TransList, 0)
if state == int64(model.TransferJobStateAll) {
countRow := d.biliDM.QueryRow(c, _countTransList, cid)
if err = countRow.Scan(&total); err != nil {
log.Error("row.ScanCount error(%v)", err)
return
}
rows, err = d.biliDM.Query(c, _TransList, cid, (pn-1)*ps, ps)
if err != nil {
log.Error("biliDM.Query(%s, %d ) error(%v)", _TransList, cid, err)
return
}
} else {
countRow := d.biliDM.QueryRow(c, _countTransListState, cid, state)
if err = countRow.Scan(&total); err != nil {
log.Error("row.ScanCount error(%v)", err)
return
}
rows, err = d.biliDM.Query(c, _TransListState, cid, state, (pn-1)*ps, ps)
if err != nil {
log.Error("biliDM.Query(%s, %d, %d) error(%v)", _TransList, cid, state, err)
return
}
}
defer rows.Close()
for rows.Next() {
dm := &model.TransList{}
if err = rows.Scan(&dm.ID, &dm.From, &dm.To, &dm.State, &dm.Ctime); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
res = append(res, dm)
}
return
}
// CheckTransferID check transfer job state by id
func (d *Dao) CheckTransferID(c context.Context, id int64) (job *model.TransferJobInfo, err error) {
job = new(model.TransferJobInfo)
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
}
// 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()
}

View File

@@ -0,0 +1,51 @@
package dao
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestInsertTransferJob(t *testing.T) {
var (
from, to, mid int64 = 1, 2, 3
offset = 1.11
)
Convey("insert a transfer job to mysql", t, func() {
_, err := testDao.InsertTransferJob(context.TODO(), from, to, mid, offset, 0)
So(err, ShouldBeNil)
})
}
func TestTransferList(t *testing.T) {
var cid, state int64 = 2, 3
Convey("test transfer job list ", t, func() {
res, _, err := testDao.TransferList(context.TODO(), cid, state, 1, 20)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}
func TestCheckTransferID(t *testing.T) {
var (
c = context.TODO()
id int64 = 265
)
Convey("test check trans by id", t, func() {
_, err := testDao.CheckTransferID(c, id)
So(err, ShouldBeNil)
})
}
func TestSetTransferState(t *testing.T) {
var (
c = context.TODO()
id int64 = 265
state int8
)
Convey("test change transfer job state", t, func() {
_, err := testDao.SetTransferState(c, id, state)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,56 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"dao_test.go",
"query_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/dm/conf:go_default_library",
"//library/log:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"query.go",
],
importpath = "go-common/app/admin/main/dm/dao/oplog",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/dm/conf:go_default_library",
"//app/admin/main/dm/model/oplog:go_default_library",
"//library/conf/env:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//vendor/github.com/pkg/errors: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,23 @@
package oplog
import (
"go-common/app/admin/main/dm/conf"
bm "go-common/library/net/http/blademaster"
)
// Dao dao struct for querying infoc data storing in hbase
type Dao struct {
httpCli *bm.Client
key, secret, infocQueryURL string
}
// New new a Dao instance and init.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
key: c.HTTPInfoc.ClientConfig.Key,
secret: c.HTTPInfoc.ClientConfig.Secret,
httpCli: bm.NewClient(c.HTTPInfoc.ClientConfig),
infocQueryURL: c.HTTPInfoc.InfocQueryURL,
}
return
}

View File

@@ -0,0 +1,24 @@
package oplog
import (
"testing"
"go-common/app/admin/main/dm/conf"
"go-common/library/log"
)
var (
dao *Dao
)
func TestMain(m *testing.M) {
var err error
conf.ConfPath = "../../cmd/dm-admin-test.toml"
if err = conf.Init(); err != nil {
log.Error("conf.Init(%v)", err)
return
}
dao = New(conf.Conf)
m.Run()
//log.Close()
}

View File

@@ -0,0 +1,154 @@
package oplog
import (
"bytes"
"context"
"crypto/md5"
"encoding/hex"
"fmt"
"math"
"net/url"
"sort"
"strconv"
"strings"
"time"
"go-common/app/admin/main/dm/model/oplog"
"go-common/library/conf/env"
"go-common/library/log"
xhttp "net/http"
pkgerr "github.com/pkg/errors"
)
const (
_singleQueryDMLogHbase = `{"startRow": "%s","stopRow": "%s","columns": {"family":"%s"}}`
_userAgent = "User-Agent"
)
var (
signParams = []string{"appKey", "timestamp", "version"}
)
// QueryOpLogs 查找弹幕操作日志前方高能这是一段极其恶心的代码1. 数据平台的key和secret是根据个人用户生成目前是我的账号madou 2.sign算法是根据appkeytimestampversion生成并大小写敏感
func (d *Dao) QueryOpLogs(c context.Context, dmid int64) (infos []*oplog.InfocResult, err error) {
v := make(url.Values, 8)
v.Set("appKey", d.key)
v.Set("signMethod", "md5")
v.Set("timestamp", time.Now().Format("2006-01-02 15:04:05"))
v.Set("version", "1.0")
//默认只查询三个月
startRow, stopRow := d.makeRowKeyScope(dmid, -3)
query := fmt.Sprintf(_singleQueryDMLogHbase, startRow, stopRow, "i")
v.Set("query", query)
var res struct {
Code int `json:"code"`
Result []*oplog.InfocResult `json:"result"`
}
if err = d.doHTTPRequest(c, d.infocQueryURL, "", v, &res); err != nil {
log.Error("berserker url(%v), err(%v)", d.infocQueryURL+"?"+v.Encode(), err)
return
}
if res.Code == 200 && len(res.Result) > 0 {
infos = res.Result
}
return
}
// doHttpRequest make a http request for data platform api
func (d *Dao) doHTTPRequest(c context.Context, uri, ip string, params url.Values, res interface{}) (err error) {
enc, err := d.sign(params)
if err != nil {
err = pkgerr.Wrapf(err, "uri:%s,params:%v", uri, params)
return
}
if enc != "" {
uri = uri + "?" + enc
}
req, err := xhttp.NewRequest(xhttp.MethodGet, uri, nil)
if err != nil {
err = pkgerr.Wrapf(err, "method:%s,uri:%s", xhttp.MethodGet, uri)
return
}
req.Header.Set(_userAgent, "haoguanwei@bilibili.com "+env.AppID)
if err != nil {
return
}
return d.httpCli.Do(c, req, res)
}
// Sign calc appkey and appsecret sign.
func (d *Dao) sign(params url.Values) (query string, err error) {
tmp := params.Encode()
signTmp := d.encode(params)
if strings.IndexByte(tmp, '+') > -1 {
tmp = strings.Replace(tmp, "+", "%20", -1)
}
var b bytes.Buffer
b.WriteString(d.secret)
b.WriteString(signTmp)
b.WriteString(d.secret)
mh := md5.Sum(b.Bytes())
// query
var qb bytes.Buffer
qb.WriteString(tmp)
qb.WriteString("&sign=")
qb.WriteString(strings.ToUpper(hex.EncodeToString(mh[:])))
query = qb.String()
return
}
// Encode encodes the values into ``URL encoded'' form
// ("bar=baz&foo=quux") sorted by key.
func (d *Dao) encode(v url.Values) string {
if v == nil {
return ""
}
var buf bytes.Buffer
keys := make([]string, 0, len(v))
for k := range v {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
found := false
for _, p := range signParams {
if p == k {
found = true
break
}
}
if !found {
continue
}
vs := v[k]
prefix := k
for _, v := range vs {
buf.WriteString(prefix)
buf.WriteString(v)
}
}
return buf.String()
}
// rowkey存储方式 [dmid倒序补零20位][(Long.Max_Value - timestamp) 的结果后10位]
func (d *Dao) makeRowKeyScope(dmid int64, months int) (startRow, endRow string) {
endTime := time.Now()
startTime := endTime.AddDate(0, months, 0)
startTmp := strconv.FormatInt(math.MaxInt64-startTime.Unix(), 10)
endTmp := strconv.FormatInt(math.MaxInt64-endTime.Unix(), 10)
endRow = d.reverse(fmt.Sprintf("%020d", dmid)) + startTmp[len(startTmp)-10:]
startRow = d.reverse(fmt.Sprintf("%020d", dmid)) + endTmp[len(endTmp)-10:]
return
}
func (d *Dao) reverse(s string) string {
n := len(s)
runes := make([]rune, n)
for _, rune := range s {
n--
runes[n] = rune
}
return string(runes[n:])
}

View File

@@ -0,0 +1,20 @@
package oplog
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestDao_QueryOpLogs(t *testing.T) {
var (
c = context.TODO()
dmid int64 = 1222
)
Convey("QueryOpLogs", t, func() {
rets, err := dao.QueryOpLogs(c, dmid)
So(err, ShouldBeNil)
So(len(rets), ShouldBeGreaterThan, 0)
})
}

View File

@@ -0,0 +1,513 @@
package dao
import (
"context"
"encoding/json"
"fmt"
"strconv"
"time"
"go-common/app/admin/main/dm/model"
"go-common/library/database/elastic"
"go-common/library/log"
"go-common/library/xstr"
)
var (
_dmMointorFields = []string{"id", "type", "pid", "oid", "state", "attr", "mcount", "ctime", "mtime", "mid", "title", "author"}
_dmReportFields = []string{"id", "dmid", "cid", "arc_aid", "arc_typeid", "dm_owner_uid", "dm_msg", "count", "content", "up_op",
"state", "uid", "rp_time", "reason", "arc_title", "dm_deleted", "arc_mid", "pool_id", "model", "score", "dm_ctime", "ctime", "mtime"}
)
// 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)
}
// SearchMonitor get monitor list from search
func (d *Dao) SearchMonitor(c context.Context, tp int32, pid, oid, mid int64, attr int32, kw, sort, order string, page, size int64) (data *model.SearchMonitorResult, err error) {
req := d.esCli.NewRequest("dm_monitor_list").Index("dm_monitoring").Fields(_dmMointorFields...).Pn(int(page)).Ps(int(size))
if tp > 0 {
req.WhereEq("type", tp)
}
if pid > 0 {
req.WhereEq("pid", pid)
}
if oid > 0 {
req.WhereEq("oid", oid)
}
if mid > 0 {
req.WhereEq("mid", mid)
}
if len(kw) > 0 {
req.WhereLike([]string{"title"}, []string{kw}, false, elastic.LikeLevelLow)
}
if attr != 0 {
req.WhereEq("attr_format", attr)
} else {
req.WhereIn("attr_format", []int64{int64(model.AttrSubMonitorBefore + 1), int64(model.AttrSubMonitorAfter + 1)})
}
if len(sort) > 0 && len(order) > 0 {
req.Order(order, sort)
}
if err = req.Scan(c, &data); err != nil {
log.Error("SearchMonitor:Scan params(%s) error(%v)", req.Params(), err)
return
}
if data == nil || data.Page == nil {
err = fmt.Errorf("data or data.Page nil")
log.Error("SearchMonitor params(%s) error(%v)", req.Params(), err)
return
}
return
}
// SearchReport2 .
func (d *Dao) SearchReport2(c context.Context, params *model.ReportListParams) (data *model.SearchReportResult, err error) {
req := d.esCli.NewRequest("dmreport").Index(d.rptSearchIndex()).Fields(_dmReportFields...).Ps(int(params.PageSize)).Pn(int(params.Page))
if len(params.Tids) > 0 {
req.WhereIn("arc_typeid", params.Tids)
}
if len(params.RpTypes) > 0 {
req.WhereIn("reason", params.RpTypes)
}
if params.Aid > 0 {
req.WhereEq("arc_aid", params.Aid)
}
if params.Cid > 0 {
req.WhereEq("cid", params.Cid)
}
if params.UID > 0 {
req.WhereEq("dm_owner_uid", params.UID)
} else {
req.WhereNot(elastic.NotTypeEq, "dm_owner_uid").WhereEq("dm_owner_uid", 0)
}
if params.RpUID > 0 {
req.WhereEq("uid", params.RpUID)
}
if len(params.States) > 0 {
req.WhereIn("state", params.States)
}
if len(params.UpOps) > 0 {
req.WhereIn("up_op", params.UpOps)
}
if params.Start != "" || params.End != "" {
req.WhereRange("rp_time", params.Start, params.End, elastic.RangeScopeLcRc)
}
if params.Keyword != "" {
req.WhereLike([]string{"dm_msg"}, []string{params.Keyword}, false, elastic.LikeLevelLow)
}
if len(params.Sort) > 0 && len(params.Order) > 0 {
req.Order(params.Order, params.Sort)
}
if err = req.Scan(c, &data); err != nil {
log.Error("SearchReport:Scan params(%s) error(%v)", req.Params(), err)
return
}
if data == nil || data.Page == nil {
err = fmt.Errorf("data or data.Page nil")
log.Error("SearchReport params(%s) error(%v)", req.Params(), err)
return
}
return
}
// SearchReport get report list from search
func (d *Dao) SearchReport(c context.Context, page, size int64, start, end, order, sort, keyword string, tid, rpID, state, upOp []int64, rt *model.Report) (data *model.SearchReportResult, err error) {
req := d.esCli.NewRequest("dmreport").Index(d.rptSearchIndex()).Fields(_dmReportFields...).Ps(int(size)).Pn(int(page))
if len(tid) > 0 {
req.WhereIn("arc_typeid", tid)
}
if len(rpID) > 0 {
req.WhereIn("reason", rpID)
}
if rt.Aid != -1 {
req.WhereEq("arc_aid", rt.Aid)
}
if rt.Cid != -1 {
req.WhereEq("cid", rt.Cid)
}
if rt.UID != -1 {
req.WhereEq("dm_owner_uid", rt.UID)
} else {
req.WhereNot(elastic.NotTypeEq, "dm_owner_uid").WhereEq("dm_owner_uid", 0)
}
if rt.RpUID != -1 {
req.WhereEq("uid", rt.RpUID)
}
if len(state) > 0 {
req.WhereIn("state", state)
}
if len(upOp) > 0 {
req.WhereIn("up_op", (upOp))
}
if start != "" || end != "" {
req.WhereRange("rp_time", start, end, elastic.RangeScopeLcRc)
}
if keyword != "" {
req.WhereLike([]string{"dm_msg"}, []string{keyword}, false, elastic.LikeLevelLow)
}
if len(sort) > 0 && len(order) > 0 {
req.Order(order, sort)
}
if err = req.Scan(c, &data); err != nil {
log.Error("SearchReport:Scan params(%s) error(%v)", req.Params(), err)
return
}
if data == nil || data.Page == nil {
err = fmt.Errorf("data or data.Page nil")
log.Error("SearchReport params(%s) error(%v)", req.Params(), err)
return
}
return
}
// SearchReportByID search report by cid and dmids.
func (d *Dao) SearchReportByID(c context.Context, dmids []int64) (data *model.SearchReportResult, err error) {
req := d.esCli.NewRequest("dmreport").Index(d.rptSearchIndex()).Fields(_dmReportFields...).Ps(100)
req.WhereIn("dmid", dmids)
if err = req.Scan(c, &data); err != nil {
log.Error("SearchReportByID:Scan params(%s) error(%v)", req.Params(), err)
return
}
if data == nil || data.Page == nil {
err = fmt.Errorf("data or data.Page nil")
log.Error("SearchReportByID params(%s) error(%v)", req.Params(), err)
return
}
return
}
// UptSearchReport 强制更新举报搜索索引 使用 v3
func (d *Dao) UptSearchReport(c context.Context, uptRpts []*model.UptSearchReport) (err error) {
upt := d.esCli.NewUpdate("dmreport")
var t time.Time
for _, rpt := range uptRpts {
t, err = time.ParseInLocation("2006-01-02 15:04:05", rpt.Ctime, time.Local)
if err != nil {
log.Error("time.ParseInLocation(%s) error(%v)", rpt.Ctime, err)
return
}
upt.AddData(fmt.Sprintf("dmreport_%d", t.Year()), rpt)
}
if err = upt.Do(c); err != nil {
log.Error("update.Do() error(%v)", err)
}
return
}
// SearchDM 搜索弹幕
func (d *Dao) SearchDM(c context.Context, p *model.SearchDMParams) (data *model.SearchDMData, err error) {
var (
order = "ctime"
sort = "desc"
req *elastic.Request
)
req = d.esCli.NewRequest("dm").Index(fmt.Sprintf("dm_%03d", p.Oid%_indexSharding)).Fields("id").Ps(int(p.Size)).Pn(int(p.Page))
req.WhereEq("oid", p.Oid)
if p.Mid != model.CondIntNil {
req.WhereEq("mid", p.Mid)
}
if p.State != "" {
if states, err1 := xstr.SplitInts(p.State); err1 == nil {
req.WhereIn("state", states)
}
}
if p.Pool != "" {
if pools, err1 := xstr.SplitInts(p.Pool); err1 == nil {
req.WhereIn("pool", pools)
}
}
if p.Attrs != "" {
if attrs, err1 := xstr.SplitInts(p.Attrs); err1 == nil {
req.WhereIn("attr_format", attrs)
}
}
if p.IP != "" {
req.WhereEq("ip_format", p.IP)
}
switch {
case p.ProgressFrom != model.CondIntNil && p.ProgressTo != model.CondIntNil:
req.WhereRange("progress", p.ProgressFrom, p.ProgressTo, elastic.RangeScopeLcRc)
case p.ProgressFrom != model.CondIntNil:
req.WhereRange("progress", p.ProgressFrom, nil, elastic.RangeScopeLcRc)
case p.ProgressTo != model.CondIntNil:
req.WhereRange("progress", nil, p.ProgressTo, elastic.RangeScopeLcRc)
}
switch {
case p.CtimeFrom != model.CondIntNil && p.CtimeTo != model.CondIntNil:
req.WhereRange("ctime", time.Unix(p.CtimeFrom, 0).Format("2006-01-02 15:04:05"), time.Unix(p.CtimeTo, 0).Format("2006-01-02 15:04:05"), elastic.RangeScopeLcRc)
case p.CtimeFrom != model.CondIntNil:
req.WhereRange("ctime", time.Unix(p.CtimeFrom, 0).Format("2006-01-02 15:04:05"), nil, elastic.RangeScopeLcRc)
case p.CtimeTo != model.CondIntNil:
req.WhereRange("ctime", nil, time.Unix(p.CtimeTo, 0).Format("2006-01-02 15:04:05"), elastic.RangeScopeLcRc)
}
if p.Keyword != "" {
req.WhereLike([]string{"kwmsg"}, []string{p.Keyword}, false, elastic.LikeLevelHigh)
}
if p.Order != "" {
order = p.Order
}
if p.Sort == "asc" {
sort = p.Sort
}
req.Order(order, sort)
if err = req.Scan(c, &data); err != nil {
log.Error("SearchDM:Scan params(%s) error(%v)", req.Params(), err)
return
}
if data == nil || data.Page == nil {
err = fmt.Errorf("data or data.Page nil")
log.Error("SearchDM params(%s) error(%v)", req.Params(), err)
return
}
return
}
// SearchProtectCount get protected dm count.
func (d *Dao) SearchProtectCount(c context.Context, tp int32, oid int64) (count int64, err error) {
var res struct {
Result map[string][]struct {
Key string `json:"key"`
Count int64 `json:"doc_count"`
} `json:"result"`
}
order := []map[string]string{{"attr": "desc"}}
req := d.esCli.NewRequest("dm").Fields("attr").Index(fmt.Sprintf("dm_%03d", d.hitIndex(oid)))
req.WhereEq("oid", oid).WhereIn("attr_format", "1").GroupBy(elastic.EnhancedModeGroupBy, "attr", order)
req.Pn(1).Ps(10)
if err = req.Scan(c, &res); err != nil {
log.Error("req.Scan() error(%v)", err)
return
}
if values, ok := res.Result["group_by_attr"]; ok {
for _, v := range values {
count = count + v.Count
}
}
return
}
// UpSearchDMState 通知搜索服务更新弹幕状态
func (d *Dao) UpSearchDMState(c context.Context, tp int32, state int32, dmidM map[int64][]int64) (err error) {
upt := d.esCli.NewUpdate("dm")
for oid, dmids := range dmidM {
for _, dmid := range dmids {
data := &model.UptSearchDMState{
ID: dmid,
Oid: oid,
State: state,
Type: tp,
Mtime: time.Now().Format("2006-01-02 15:04:05"),
}
upt.AddData(fmt.Sprintf("dm_%03d", oid%_indexSharding), data)
}
}
if err = upt.Do(c); err != nil {
log.Error("update.Do() params(%s) error(%v)", upt.Params(), err)
}
return
}
// UpSearchDMPool 通知搜索服务更新弹幕池
func (d *Dao) UpSearchDMPool(c context.Context, tp int32, oid int64, pool int32, dmids []int64) (err error) {
upt := d.esCli.NewUpdate("dm")
for _, dmid := range dmids {
data := &model.UptSearchDMPool{
ID: dmid,
Oid: oid,
Pool: pool,
Type: tp,
Mtime: time.Now().Format("2006-01-02 15:04:05"),
}
upt.AddData(fmt.Sprintf("dm_%03d", oid%_indexSharding), data)
}
if err = upt.Do(c); err != nil {
log.Error("update.Do() params(%s) error(%v)", upt.Params(), err)
}
return
}
// UpSearchDMAttr 通知搜索服务更新弹幕属性
func (d *Dao) UpSearchDMAttr(c context.Context, tp int32, oid int64, attr int32, dmids []int64) (err error) {
var bits []int64
for k, v := range strconv.FormatInt(int64(attr), 2) {
if v == 49 {
bits = append(bits, int64(k+1))
}
}
upt := d.esCli.NewUpdate("dm")
for _, dmid := range dmids {
data := &model.UptSearchDMAttr{
ID: dmid,
Oid: oid,
Attr: attr,
AttrFormat: bits,
Type: tp,
Mtime: time.Now().Format("2006-01-02 15:04:05"),
}
upt.AddData(fmt.Sprintf("dm_%03d", oid%_indexSharding), data)
}
if err = upt.Do(c); err != nil {
log.Error("update.Do() params(%s) error(%v)", upt.Params(), err)
}
return
}
// SearchSubjectLog get subject log
func (d *Dao) SearchSubjectLog(c context.Context, tp int32, oid int64) (data []*model.SubjectLog, err error) {
req := d.esCli.NewRequest("log_audit").Index("log_audit_31_all").Fields("uid", "uname", "oid", "ctime", "action", "extra_data").WhereEq("oid", oid).WhereEq("type", tp)
req.Ps(20).Order("ctime", "desc")
res := &model.SearchSubjectLog{}
if err = req.Scan(c, &res); err != nil || res == nil {
log.Error("SearchSubcetLog:Scan params(%s) error(%v)", req.Params(), err)
return
}
data = make([]*model.SubjectLog, 0)
s := new(struct {
Comment string `json:"comment"`
})
for _, v := range res.Result {
if err = json.Unmarshal([]byte(v.ExtraData), s); err != nil {
log.Error("json.Unmarshal(%s) error(%v)", v.ExtraData, err)
return
}
log := &model.SubjectLog{
UID: v.UID,
Uname: v.Uname,
Oid: v.Oid,
Action: v.Action,
Comment: s.Comment,
Ctime: v.Ctime,
}
data = append(data, log)
}
return
}
// UpSearchRecentDMState .
func (d *Dao) UpSearchRecentDMState(c context.Context, tp int32, state int32, dmidM map[int64][]int64) (err error) {
upt := d.esCli.NewUpdate("dm_home")
year, month, _ := time.Now().Date()
yearPre, monthPre, _ := time.Now().AddDate(0, -1, 0).Date()
for oid, dmids := range dmidM {
for _, dmid := range dmids {
data := &model.UptSearchDMState{
ID: dmid,
Oid: oid,
State: state,
Type: tp,
Mtime: time.Now().Format("2006-01-02 15:04:05"),
}
upt.AddData(fmt.Sprintf("dm_home_%v",
fmt.Sprintf("%d_%02d", yearPre, int(monthPre)),
), data)
upt.AddData(fmt.Sprintf("dm_home_%v",
fmt.Sprintf("%d_%02d", year, int(month)),
), data)
}
}
if err = upt.Do(c); err != nil {
log.Error("update.Do() params(%s) error(%v)", upt.Params(), err)
}
return
}
// UpSearchRecentDMPool .
func (d *Dao) UpSearchRecentDMPool(c context.Context, tp int32, oid int64, pool int32, dmids []int64) (err error) {
upt := d.esCli.NewUpdate("dm_home")
year, month, _ := time.Now().Date()
yearPre, monthPre, _ := time.Now().AddDate(0, -1, 0).Date()
for _, dmid := range dmids {
data := &model.UptSearchDMPool{
ID: dmid,
Oid: oid,
Pool: pool,
Type: tp,
Mtime: time.Now().Format("2006-01-02 15:04:05"),
}
upt.AddData(fmt.Sprintf("dm_home_%v",
fmt.Sprintf("%d_%02d", yearPre, int(monthPre)),
), data)
upt.AddData(fmt.Sprintf("dm_home_%v",
fmt.Sprintf("%d_%02d", year, int(month)),
), data)
}
if err = upt.Do(c); err != nil {
log.Error("update.Do() params(%s) error(%v)", upt.Params(), err)
}
return
}
// UpSearchRecentDMAttr .
func (d *Dao) UpSearchRecentDMAttr(c context.Context, tp int32, oid int64, attr int32, dmids []int64) (err error) {
var bits []int64
for k, v := range strconv.FormatInt(int64(attr), 2) {
if v == 49 {
bits = append(bits, int64(k+1))
}
}
upt := d.esCli.NewUpdate("dm_home")
year, month, _ := time.Now().Date()
yearPre, monthPre, _ := time.Now().AddDate(0, -1, 0).Date()
for _, dmid := range dmids {
data := &model.UptSearchDMAttr{
ID: dmid,
Oid: oid,
Attr: attr,
AttrFormat: bits,
Type: tp,
Mtime: time.Now().Format("2006-01-02 15:04:05"),
}
upt.AddData(fmt.Sprintf("dm_home_%v",
fmt.Sprintf("%d_%02d", yearPre, int(monthPre)),
), data)
upt.AddData(fmt.Sprintf("dm_home_%v",
fmt.Sprintf("%d_%02d", year, int(month)),
), data)
}
if err = upt.Do(c); err != nil {
log.Error("update.Do() params(%s) error(%v)", upt.Params(), err)
}
return
}
// SearchSubject get subject log list from search
func (d *Dao) SearchSubject(c context.Context, req *model.SearchSubjectReq) (data []int64, page *model.Page, err error) {
r := d.esCli.NewRequest("dm_monitor_list").Index("dm_monitoring").Fields("oid")
if len(req.Oids) > 0 {
r.WhereIn("oid", req.Oids)
}
if len(req.Mids) > 0 {
r.WhereIn("mid", req.Mids)
}
if len(req.Aids) > 0 {
r.WhereIn("pid", req.Aids)
}
if len(req.Attrs) > 0 {
r.WhereIn("attr_format", req.Attrs)
}
if req.State != model.CondIntNil {
r.WhereEq("state", req.State)
}
r.Ps(int(req.Ps)).Pn(int(req.Pn)).Order(req.Order, req.Sort)
res := &model.SearchSubjectResult{}
if err = r.Scan(c, &res); err != nil {
log.Error("SearchSubject:Scan params(%s) error(%v)", r.Params(), err)
return
}
if res == nil || res.Page == nil {
err = fmt.Errorf("data or data.Page nil")
log.Error("SearchSubject params(%s) error(%v)", r.Params(), err)
return
}
for _, v := range res.Result {
data = append(data, v.Oid)
}
page = res.Page
return
}

View File

@@ -0,0 +1,50 @@
package dao
import (
"context"
"go-common/app/admin/main/dm/model"
"go-common/library/database/elastic"
"go-common/library/log"
)
var (
_subtitleFields = []string{"oid", "id"}
)
// SearchSubtitle .
func (d *Dao) SearchSubtitle(c context.Context, arg *model.SubtitleSearchArg) (res *model.SearchSubtitleResult, err error) {
var (
req *elastic.Request
fields []string
)
fields = _subtitleFields
req = d.esCli.NewRequest("dm_subtitle").Index("subtitle").Fields(fields...).Pn(int(arg.Pn)).Ps(int(arg.Ps))
if arg.Aid > 0 {
req.WhereEq("aid", arg.Aid)
}
if arg.Mid > 0 {
req.WhereEq("mid", arg.Mid)
}
if arg.Oid > 0 {
req.WhereEq("oid", arg.Oid)
}
if arg.Mid > 0 {
req.WhereEq("mid", arg.Mid)
}
if arg.Status > 0 {
req.WhereEq("status", arg.Status)
}
if arg.UpperMid > 0 {
req.WhereEq("up_mid", arg.UpperMid)
}
if arg.Lan > 0 {
req.WhereEq("lan", arg.Lan)
}
req.Order("mtime", "desc")
if err = req.Scan(c, &res); err != nil {
log.Error("elastic search(%s) error(%v)", req.Params(), err)
return
}
return
}

View File

@@ -0,0 +1,27 @@
package dao
import (
"context"
"testing"
"go-common/app/admin/main/dm/model"
. "github.com/smartystreets/goconvey/convey"
)
func TestSearchSubtitle(t *testing.T) {
var (
arg = &model.SubtitleSearchArg{
Oid: int64(10131981),
}
)
Convey("search subtitles", t, func() {
res, err := testDao.SearchSubtitle(context.Background(), arg)
So(err, ShouldBeNil)
So(res, ShouldNotBeEmpty)
t.Logf("res:%+v", res)
for _, rpt := range res.Result {
t.Logf("======%+v", rpt)
}
})
}

View File

@@ -0,0 +1,258 @@
package dao
import (
"context"
"testing"
"go-common/app/admin/main/dm/model"
. "github.com/smartystreets/goconvey/convey"
)
func TestSearchMonitor(t *testing.T) {
var (
c = context.TODO()
aid, cid, mid, p, ps int64 = 0, 0, 0, 1, 50
kw, sort, order string = "", "", ""
attr = int32(0)
tp = int32(1)
)
Convey("get monitor list from search", t, func() {
res, err := testDao.SearchMonitor(c, tp, aid, cid, mid, attr, kw, sort, order, p, ps)
So(err, ShouldBeNil)
So(res, ShouldNotBeEmpty)
t.Logf("res:%+v", res)
for _, rpt := range res.Result {
t.Logf("======%+v", rpt)
}
})
}
func TestSearchReports(t *testing.T) {
var (
c = context.TODO()
tid = []int64{}
rpID = []int64{1, 2}
upOp = []int64{0, 1, 2}
state = []int64{0, 1, 2}
rt = &model.Report{
Aid: -1,
UID: -1,
RpUID: -1,
RpType: -1,
Cid: -1,
}
)
Convey("", t, func() {
res, err := testDao.SearchReport(c, 1, 100, "", "", "rp_time", "desc", "", tid, rpID, state, upOp, rt)
So(err, ShouldBeNil)
So(res, ShouldNotBeEmpty)
t.Logf("======%+v", res.Page)
for _, rpt := range res.Result {
t.Logf("======%+v", rpt)
}
})
}
func TestSearchReportByID(t *testing.T) {
var (
c = context.TODO()
dmids = []int64{719218372}
)
Convey("", t, func() {
res, err := testDao.SearchReportByID(c, dmids)
So(err, ShouldBeNil)
So(res, ShouldNotBeEmpty)
t.Logf("===res:%v", res)
for _, rpt := range res.Result {
t.Logf("======%+v", rpt)
}
})
}
func TestSearchDM(t *testing.T) {
var (
c = context.TODO()
d = &model.SearchDMParams{
Type: 1,
Oid: 10131232,
Mid: model.CondIntNil,
ProgressFrom: model.CondIntNil,
ProgressTo: model.CondIntNil,
CtimeFrom: model.CondIntNil,
CtimeTo: model.CondIntNil,
State: "",
Pool: "",
Attrs: "1",
Page: 1,
Order: "id",
Sort: "asc",
}
)
Convey("", t, func() {
res, err := testDao.SearchDM(c, d)
So(err, ShouldBeNil)
So(res, ShouldNotBeEmpty)
t.Logf("===page:%+v", res.Page)
for _, rpt := range res.Result {
t.Logf("======%+v", rpt)
}
})
}
func TestSendJudgement(t *testing.T) {
var (
c = context.TODO()
li = make([]*model.ReportJudge, 0)
)
i := &model.ReportJudge{
MID: 150781,
Operator: "zhang",
OperID: 121,
OContent: "test dm",
OTitle: "test archive",
OType: 2,
OURL: "https://www.bilibili.com",
ReasonType: 2,
AID: 11,
OID: 22,
RPID: 33,
Page: 1,
BTime: int64(1517824276),
}
li = append(li, i)
Convey("test send judgement", t, func() {
err := testDao.SendJudgement(c, li)
So(err, ShouldBeNil)
})
}
func TestUpSearchDMState(t *testing.T) {
var (
tp int32 = 1
state int32 = 2
dmids = map[int64][]int64{10131232: {1909860427366403, 1909932482887683}}
)
Convey("", t, func() {
err := testDao.UpSearchDMState(context.TODO(), tp, state, dmids)
So(err, ShouldBeNil)
})
}
func TestUpSearchDMAttr(t *testing.T) {
var (
tp int32 = 1
oid int64 = 10131232
attr int32 = 1
dmids = []int64{1909860427366403, 1909932482887683}
)
Convey("", t, func() {
err := testDao.UpSearchDMAttr(context.TODO(), tp, oid, attr, dmids)
So(err, ShouldBeNil)
})
}
func TestUpSearchDMPool(t *testing.T) {
var (
tp int32 = 1
oid int64 = 10131232
pool int32 = 1
dmids = []int64{1909860427366403, 1909932482887683}
)
Convey("", t, func() {
err := testDao.UpSearchDMPool(context.TODO(), tp, oid, pool, dmids)
So(err, ShouldBeNil)
})
}
func TestUptSearchReport(t *testing.T) {
var (
uptRpt = &model.UptSearchReport{
DMid: 719218991,
Ctime: "2018-04-27 11:06:46",
Mtime: "2018-06-07 11:06:46",
State: model.StatSecondIgnore,
}
uptRpts = []*model.UptSearchReport{uptRpt}
)
Convey("test update search report", t, func() {
err := testDao.UptSearchReport(context.TODO(), uptRpts)
So(err, ShouldBeNil)
})
}
func TestDaoSearchSubjectLog(t *testing.T) {
Convey("SearchSubjectLog", t, func() {
data, err := testDao.SearchSubjectLog(context.TODO(), 1, 1221)
So(err, ShouldBeNil)
So(data, ShouldNotBeNil)
for _, v := range data {
t.Logf("====%+v", v)
}
})
}
func TestDaoSearchSubject(t *testing.T) {
r := &model.SearchSubjectReq{
// Oids: []int64{10131821},
Mids: []int64{0},
Sort: "desc",
Order: "mtime",
Pn: 1,
Ps: 5,
State: int64(model.CondIntNil),
}
Convey("SearchSubject", t, func() {
data, page, err := testDao.SearchSubject(context.TODO(), r)
So(err, ShouldBeNil)
for _, v := range data {
t.Logf("====%+v", v)
}
t.Logf("====%+v", page)
})
}
func TestSearchProtectCount(t *testing.T) {
Convey("get protect dm count", t, func() {
count, err := testDao.SearchProtectCount(context.TODO(), 1, 1221)
So(err, ShouldBeNil)
t.Log(count)
})
}
func TestUpSearchRecemtDMState(t *testing.T) {
var (
tp int32 = 1
state int32 = 2
dmids = map[int64][]int64{10131232: {1909860427366403, 1909932482887683}}
)
Convey("", t, func() {
err := testDao.UpSearchRecentDMState(context.TODO(), tp, state, dmids)
So(err, ShouldBeNil)
})
}
func TestUpSearchRecentDMAttr(t *testing.T) {
var (
tp int32 = 1
oid int64 = 10131232
attr int32 = 1
dmids = []int64{1909860427366403, 1909932482887683}
)
Convey("", t, func() {
err := testDao.UpSearchRecentDMAttr(context.TODO(), tp, oid, attr, dmids)
So(err, ShouldBeNil)
})
}
func TestUpSearchRecentDMPool(t *testing.T) {
var (
tp int32 = 1
oid int64 = 10131232
pool int32 = 1
dmids = []int64{1909860427366403, 1909932482887683}
)
Convey("", t, func() {
err := testDao.UpSearchRecentDMPool(context.TODO(), tp, oid, pool, dmids)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,130 @@
package dao
import (
"bytes"
"context"
"crypto/md5"
"encoding/hex"
"fmt"
"net/http"
"net/url"
"sort"
"strings"
"time"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_selectQuery = "SELECT index.dmid,index.oid,index.mid,index.state,content.msg,b_long2ip(content.ip),content.ctime FROM ods.ods_dm_index AS index, ods.ods_dm_content AS content WHERE index.dmid=content.dmid AND index.state in (0,2,6) %s limit 1000000"
)
var (
signParams = []string{"appKey", "timestamp", "version"}
)
// SendTask send task to BI
func (d *Dao) SendTask(c context.Context, taskSQL []string) (statusURL string, err error) {
var (
sql string
res struct {
Code int64 `json:"code"`
StatusURL string `json:"jobStatusUrl"`
Message string `json:"msg"`
}
params = url.Values{}
)
if len(taskSQL) > 0 {
sql = fmt.Sprintf(" AND %s", strings.Join(taskSQL, " AND "))
} else {
err = ecode.RequestErr
return
}
log.Warn("send task sql(%s)", fmt.Sprintf(_selectQuery, sql))
params.Set("appKey", "672bc22888af701529e8b3052fd2c4a7")
params.Set("query", fmt.Sprintf(_selectQuery, sql))
params.Set("timestamp", time.Now().Format("2006-01-02 15:04:05"))
params.Set("version", "1.0")
params.Set("signMethod", "md5")
uri := d.berserkerURI + "?" + sign(params)
log.Warn("send task uri(%s)", uri)
req, err := http.NewRequest(http.MethodGet, uri, nil)
if err != nil {
log.Error("http.NewRequest(%s) error(%v)", uri, err)
return
}
for i := 0; i < 3; i++ {
if err = d.httpCli.Do(c, req, &res); err != nil {
log.Error("d.httpCli.Do error:%v", err)
time.Sleep(100 * time.Millisecond)
continue
}
if res.Code != 200 {
err = fmt.Errorf("uri:%s,code:%d", uri, res.Code)
log.Error("d.res.Code error:%v", err)
time.Sleep(100 * time.Millisecond)
continue
}
break
}
if err != nil {
log.Error("d.SendTask(uri:%s) error(%v)", uri, err)
}
return res.StatusURL, err
}
// Sign calculate appkey and appsecret sign.
func sign(params url.Values) (query string) {
tmp := params.Encode()
signTmp := encode(params)
if strings.IndexByte(tmp, '+') > -1 {
tmp = strings.Replace(tmp, "+", "%20", -1)
}
var b bytes.Buffer
b.WriteString("bee5e4b744a22a59abbaecc7ade5de9c")
b.WriteString(signTmp)
b.WriteString("bee5e4b744a22a59abbaecc7ade5de9c")
mh := md5.Sum(b.Bytes())
// fmt.Println(b.String())
// query
var qb bytes.Buffer
qb.WriteString(tmp)
qb.WriteString("&sign=")
qb.WriteString(strings.ToUpper(hex.EncodeToString(mh[:])))
query = qb.String()
return
}
// Encode encodes the values into ``sign encoded'' form
// ("barbazfooquux") sorted by key.
func encode(v url.Values) string {
if v == nil {
return ""
}
var buf bytes.Buffer
keys := make([]string, 0, len(v))
for k := range v {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
found := false
for _, p := range signParams {
if p == k {
found = true
break
}
}
if !found {
continue
}
vs := v[k]
prefix := k
for _, v := range vs {
buf.WriteString(prefix)
buf.WriteString(v)
}
}
return buf.String()
}

View File

@@ -0,0 +1,49 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoSendTask(t *testing.T) {
convey.Convey("SendTask", t, func(ctx convey.C) {
var (
c = context.Background()
taskSQL = []string{"index.mid=3458517", "content.log_date<=20181111"}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
statusURL, err := testDao.SendTask(c, taskSQL)
ctx.Convey("Then err should be nil.statusURL should not be nil.", func(ctx convey.C) {
// ctx.So(err, convey.ShouldBeNil)
// ctx.So(statusURL, convey.ShouldNotBeNil)
t.Logf("%v %s\n", err, statusURL)
})
})
})
}
// func TestBerserker(t *testing.T) {
// params := url.Values{}
// params.Set("appKey", "672bc22888af701529e8b3052fd2c4a7")
// params.Set("query", "select * from ods.ods_dm_index where dmid<1000 limit 10")
// params.Set("timestamp", time.Now().Format("2006-01-02 15:04:05"))
// params.Set("version", "1.0")
// params.Set("signMethod", "md5")
// s := _berserker + "?" + sign(params)
// fmt.Println(s)
// body, err := oget(s)
// if err != nil {
// t.Errorf("url(%s) error(%s)", s, err)
// t.FailNow()
// }
// fmt.Println(string(body))
// var out bytes.Buffer
// if err = json.Indent(&out, body, "", " "); err != nil {
// t.Fatal(err)
// t.FailNow()
// }
// fmt.Println(out.String())
// }

View File

@@ -0,0 +1,99 @@
package dao
import (
"context"
"fmt"
"net/url"
"go-common/app/admin/main/dm/model"
"go-common/library/log"
"go-common/library/xstr"
)
const (
_views = "/videoup/views"
_types = "/videoup/types"
_season = "/pgc/admin/season/dm/aids"
)
// TypeInfo TypeInfo
func (d *Dao) TypeInfo(c context.Context) (types map[int64]*model.ArchiveType, err error) {
var (
res struct {
Code int64 `json:"code"`
Data map[int64]*model.ArchiveType `json:"data"`
Message string `json:"message"`
}
)
v := make(url.Values)
if err = d.httpCli.Get(c, d.typesURI, "", v, &res); err != nil {
log.Error("d.httpCli.Get(%s) error(%v)", d.typesURI, err)
return
}
if res.Code != 0 {
err = fmt.Errorf("%v", res)
log.Error("d.httpClient.Get(%s) code(%d)", d.typesURI, res.Code)
}
types = res.Data
return
}
// ArchiveVideos return archive and video info.
func (d *Dao) ArchiveVideos(c context.Context, aids []int64) (avm map[int64]*model.ArcVideo, err error) {
var (
res struct {
Code int64 `json:"code"`
Data map[int64]*model.ArcVideo `json:"data"`
Message string `json:"message"`
}
v = make(url.Values)
)
v.Set("aids", xstr.JoinInts(aids))
if err = d.httpCli.Get(c, d.viewsURI, "", v, &res); err != nil {
log.Error("d.httpClient.Get(%s) error(%v)", d.viewsURI, err)
return
}
if res.Code != 0 {
err = fmt.Errorf("%v", res)
log.Error("d.httpClient.Get(%s) code(%d)", d.viewsURI, res.Code)
return
}
avm = res.Data
return
}
// SeasonInfos return season infos
func (d *Dao) SeasonInfos(c context.Context, IDType string, id int64) (aids, oids []int64, err error) {
var (
res struct {
Code int64 `json:"code"`
Message string `json:"message"`
Data []*model.SeasonInfo `json:"result"`
}
params = make(url.Values, 1)
)
switch IDType {
case "ep":
params.Set("epid", fmt.Sprint(id))
case "ss":
params.Set("season_id", fmt.Sprint(id))
default:
err = fmt.Errorf("season type(%s) error", IDType)
log.Error("d.SeasonInfos error(%v)", err)
return
}
if err = d.httpSearch.Get(c, d.seasonURI, "", params, &res); err != nil {
log.Error("d.httpSearch.Get(uri:%s,params:%s) error(%v)", d.seasonURI, params.Encode(), err)
return
}
if res.Code != 0 {
err = fmt.Errorf("uri:%s,code:%d", d.seasonURI, res.Code)
log.Error("d.SeasonInfos error(%v)", err)
return
}
for _, v := range res.Data {
aids = append(aids, v.Aid)
oids = append(oids, v.Cid)
}
return
}

View File

@@ -0,0 +1,24 @@
package dao
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestTypeInfo(t *testing.T) {
Convey("", t, func() {
types, err := testDao.TypeInfo(context.TODO())
So(types, ShouldNotBeEmpty)
So(err, ShouldBeNil)
})
}
func TestArchiveVideos(t *testing.T) {
Convey("", t, func() {
avm, err := testDao.ArchiveVideos(context.TODO(), []int64{10110320, 123, 3})
So(avm, ShouldNotBeEmpty)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,40 @@
package dao
import (
"context"
"net/url"
"strconv"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
)
const (
_workFlowAppealDelete = "/x/internal/workflow/appeal/v3/delete"
)
// WorkFlowAppealDelete .
func (d *Dao) WorkFlowAppealDelete(c context.Context, bid, oid, subtitleID int64) (err error) {
var (
res struct {
Code int `json:"code"`
Message string `json:"message"`
}
params = url.Values{}
ip = metadata.String(c, metadata.RemoteIP)
)
params.Set("bid", strconv.FormatInt(bid, 10))
params.Set("oid", strconv.FormatInt(oid, 10))
params.Set("eid", strconv.FormatInt(subtitleID, 10))
if err = d.httpCli.Post(c, d.workFlowURI, ip, params, &res); err != nil {
log.Error("WorkFlowTagList(params:%v),error(%v)", params, err)
return
}
if err = ecode.Int(res.Code); err != ecode.OK {
log.Error("WorkFlowTagList(params:%v),error(%v)", params, err)
return
}
err = nil
return
}

View File

@@ -0,0 +1,22 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoWorkFlowAppealDelete(t *testing.T) {
convey.Convey("WorkFlowAppealDelete", t, func(ctx convey.C) {
var (
c = context.Background()
bid = int64(0)
oid = int64(0)
subtitleID = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.WorkFlowAppealDelete(c, bid, oid, subtitleID)
})
})
}

View File

@@ -0,0 +1,67 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"adv_test.go",
"filter_test.go",
"http_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = ["//app/admin/main/dm/conf:go_default_library"],
)
go_library(
name = "go_default_library",
srcs = [
"adv.go",
"dm.go",
"filter.go",
"http.go",
"mask.go",
"monitor.go",
"report.go",
"shield.go",
"subject.go",
"subtitle.go",
"task.go",
"transfer.go",
],
importpath = "go-common/app/admin/main/dm/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/dm/conf:go_default_library",
"//app/admin/main/dm/model:go_default_library",
"//app/admin/main/dm/service:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/binding:go_default_library",
"//library/net/http/blademaster/middleware/permit:go_default_library",
"//library/net/http/blademaster/middleware/verify: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,60 @@
package http
import (
"strconv"
"go-common/app/admin/main/dm/model"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
)
// advList 高级弹幕列表
func advList(c *bm.Context) {
var (
p = c.Request.Form
pn = int64(1)
ps = int64(50)
)
dmInid, err := strconv.ParseInt(p.Get("oid"), 10, 64)
if err != nil || dmInid == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
typ := p.Get("bType")
if typ == "" {
c.JSON(nil, ecode.RequestErr)
return
}
mode := p.Get("mode")
if mode == "" {
c.JSON(nil, ecode.RequestErr)
return
}
if p.Get("pn") != "" {
if pn, err = strconv.ParseInt(p.Get("pn"), 10, 64); err != nil || pn <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
}
if p.Get("ps") != "" {
if ps, err = strconv.ParseInt(p.Get("ps"), 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
result, total, err := dmSvc.Advances(c, dmInid, typ, mode, pn, ps)
if err != nil {
c.JSON(nil, err)
return
}
pageInfo := &model.PageInfo{
Num: pn,
Size: ps,
Total: total,
}
data := &model.AdvanceRes{
Result: result,
Page: pageInfo,
}
c.JSON(data, nil)
}

View File

@@ -0,0 +1,35 @@
package http
import (
"crypto/md5"
"encoding/hex"
"fmt"
"net/url"
"strconv"
"testing"
"time"
)
func TestAdvList(t *testing.T) {
params := url.Values{}
params.Set("oid", "10108682")
params.Set("bType", "all")
params.Set("mode", "all")
params.Set("appkey", "53e2fa226f5ad348")
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
mh := md5.Sum([]byte(params.Encode() + "3cf6bd1b0ff671021da5f424fea4b04a"))
params.Set("sign", hex.EncodeToString(mh[:]))
s := managerHost + "/x/admin/dm/adv/list?" + params.Encode()
body, err := oget(s)
if err != nil {
t.Errorf("url(%s) error(%s)", s, err)
t.FailNow()
}
if err = ccode(body); err != nil {
t.Fatal(err, string(body))
t.FailNow()
}
t.Logf("=========%v\n", body)
fmt.Println(string(body))
}

View File

@@ -0,0 +1,286 @@
package http
import (
"strconv"
"go-common/app/admin/main/dm/model"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/xstr"
)
func contentList(c *bm.Context) {
var (
v = new(model.SearchDMParams)
)
if err := c.Bind(v); err != nil {
return
}
c.JSON(dmSvc.DMSearch(c, v))
}
// xmlCacheFlush flush danmu xml cache.
func xmlCacheFlush(c *bm.Context) {
var (
err error
tp = int64(model.SubTypeVideo)
p = c.Request.Form
)
if p.Get("type") != "" {
if tp, err = strconv.ParseInt(p.Get("type"), 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
oid, err := strconv.ParseInt(p.Get("oid"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
dmSvc.XMLCacheFlush(c, int32(tp), oid)
c.JSON(nil, nil)
}
// dmSearch danmu content List by cid
func dmSearch(c *bm.Context) {
p := c.Request.Form
params := &model.SearchDMParams{
Mid: model.CondIntNil,
State: p.Get("state"),
Pool: p.Get("pool"),
ProgressFrom: model.CondIntNil,
ProgressTo: model.CondIntNil,
CtimeFrom: model.CondIntNil,
CtimeTo: model.CondIntNil,
Page: 1,
Size: 100,
Sort: p.Get("sort"),
Order: p.Get("order"),
Keyword: p.Get("keyword"),
IP: p.Get("ip"),
Attrs: p.Get("attrs"),
}
tp, err := strconv.ParseInt(p.Get("type"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
params.Type = int32(tp)
oid, err := strconv.ParseInt(p.Get("oid"), 10, 64)
if err != nil {
log.Error("param err oid %s %v", p.Get("oid"), err)
c.JSON(nil, ecode.RequestErr)
return
}
params.Oid = oid
if p.Get("page") != "" {
if params.Page, err = strconv.ParseInt(p.Get("page"), 10, 64); err != nil {
log.Error("param err page %s %v", p.Get("page"), err)
c.JSON(nil, ecode.RequestErr)
return
}
}
if p.Get("page_size") != "" {
if params.Size, err = strconv.ParseInt(p.Get("page_size"), 10, 64); err != nil {
log.Error("param err page_size %s %v", p.Get("page_size"), err)
c.JSON(nil, ecode.RequestErr)
return
}
}
if p.Get("mid") != "" {
if params.Mid, err = strconv.ParseInt(p.Get("mid"), 10, 64); err != nil {
log.Error("param err mid %s %v", p.Get("mid"), err)
c.JSON(nil, ecode.RequestErr)
return
}
}
if p.Get("progress_from") != "" {
if params.ProgressFrom, err = strconv.ParseInt(p.Get("progress_from"), 10, 64); err != nil {
log.Error("param err progress_from %s %v", p.Get("progress_from"), err)
c.JSON(nil, ecode.RequestErr)
return
}
}
if p.Get("progress_to") != "" {
if params.ProgressTo, err = strconv.ParseInt(p.Get("progress_to"), 10, 64); err != nil {
log.Error("param err progress_to %s %v", p.Get("progress_to"), err)
c.JSON(nil, ecode.RequestErr)
return
}
}
if p.Get("ctime_from") != "" {
if params.CtimeFrom, err = strconv.ParseInt(p.Get("ctime_from"), 10, 64); err != nil {
log.Error("param err ctime_from %s %v", p.Get("ctime_from"), err)
c.JSON(nil, ecode.RequestErr)
return
}
}
if p.Get("ctime_to") != "" {
if params.CtimeTo, err = strconv.ParseInt(p.Get("ctime_to"), 10, 64); err != nil {
log.Error("param err ctime_to %s %v", p.Get("ctime_to"), err)
c.JSON(nil, ecode.RequestErr)
return
}
}
data, err := dmSvc.DMSearch(c, params)
c.JSON(data, err)
}
// editDMState batch operation by danmu content id
func editDMState(c *bm.Context) {
var (
moral, reason int64
p = c.Request.Form
)
tp, err := strconv.ParseInt(p.Get("type"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
oid, err := strconv.ParseInt(p.Get("oid"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if p.Get("reason_id") != "" {
reason, err = strconv.ParseInt(p.Get("reason_id"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
state, err := strconv.ParseInt(p.Get("state"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if p.Get("moral") != "" {
moral, err = strconv.ParseInt(p.Get("moral"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
adminID, err := strconv.ParseInt(p.Get("adminId"), 10, 64)
if err != nil || adminID <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
uname := p.Get("uname")
if uname == "" {
c.JSON(nil, ecode.RequestErr)
log.Error("empty uname is not allow")
return
}
remark := p.Get("remark")
dmids, err := xstr.SplitInts(p.Get("dmids"))
if err != nil || len(dmids) == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
err = dmSvc.EditDMState(c, int32(tp), int32(state), oid, int8(reason), dmids, float64(moral), adminID, uname, remark)
c.JSON(nil, err)
}
// editDMPool batch operation by danmu content id
func editDMPool(c *bm.Context) {
p := c.Request.Form
tp, err := strconv.ParseInt(p.Get("type"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
oid, err := strconv.ParseInt(p.Get("oid"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
pool, err := strconv.ParseInt(p.Get("pool"), 10, 64)
if err != nil || (pool != 0 && pool != 1) {
c.JSON(nil, ecode.RequestErr)
return
}
dmids, err := xstr.SplitInts(p.Get("dmids"))
if err != nil || len(dmids) == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
adminID, err := strconv.ParseInt(p.Get("adminId"), 10, 64)
if err != nil || adminID <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
err = dmSvc.EditDMPool(c, int32(tp), oid, int32(pool), dmids, adminID)
c.JSON(nil, err)
}
// editDMAttr change attr
func editDMAttr(c *bm.Context) {
var (
p = c.Request.Form
bit uint
value int32
)
tp, err := strconv.ParseInt(p.Get("type"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
oid, err := strconv.ParseInt(p.Get("oid"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
attr, err := strconv.ParseInt(p.Get("attr"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
switch attr {
case 0: // unprotect dm
bit = model.AttrProtect
value = model.AttrNo
case 1: // protect dm
bit = model.AttrProtect
value = model.AttrYes
default:
c.JSON(nil, ecode.RequestErr)
return
}
dmids, err := xstr.SplitInts(p.Get("dmids"))
if err != nil || len(dmids) == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
adminID, err := strconv.ParseInt(p.Get("adminId"), 10, 64)
if err != nil || adminID <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
err = dmSvc.EditDMAttr(c, int32(tp), oid, dmids, bit, value, adminID)
c.JSON(nil, err)
}
// dmIndexInfo get dm_index info
func dmIndexInfo(c *bm.Context) {
p := c.Request.Form
cid, err := strconv.ParseInt(p.Get("cid"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
info, err := dmSvc.DMIndexInfo(c, cid)
c.JSON(info, err)
}
func fixDMCount(c *bm.Context) {
p := c.Request.Form
aid, err := strconv.ParseInt(p.Get("aid"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
err = dmSvc.FixDMCount(c, aid)
c.JSON(nil, err)
}

View File

@@ -0,0 +1,86 @@
package http
import (
"strconv"
"go-common/app/admin/main/dm/model"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
)
func upFilters(c *bm.Context) {
var (
p = c.Request.Form
pn = int64(1)
ps = int64(50)
fType = int64(-1)
)
mid, err := strconv.ParseInt(p.Get("mid"), 10, 64)
if err != nil || mid <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if p.Get("type") != "" {
if fType, err = strconv.ParseInt(p.Get("type"), 10, 64); err != nil || fType < -1 {
c.JSON(nil, ecode.RequestErr)
return
}
}
if p.Get("pn") != "" {
if pn, err = strconv.ParseInt(p.Get("pn"), 10, 64); err != nil || pn <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
}
if p.Get("ps") != "" {
if ps, err = strconv.ParseInt(p.Get("ps"), 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
list, total, err := dmSvc.UpFilters(c, mid, fType, pn, ps)
if err != nil {
c.JSON(nil, err)
return
}
pageInfo := &model.PageInfo{
Num: pn,
Size: ps,
Total: total,
}
data := &model.UpFilterRes{
Result: list,
Page: pageInfo,
}
c.JSON(data, nil)
}
func editUpFilters(c *bm.Context) {
p := c.Request.Form
mid, err := strconv.ParseInt(p.Get("mid"), 10, 64)
if err != nil || mid <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
id, err := strconv.ParseInt(p.Get("id"), 10, 64)
if err != nil || id < 0 {
c.JSON(nil, ecode.RequestErr)
return
}
fType, err := strconv.ParseInt(p.Get("type"), 10, 64)
if err != nil || fType < 0 {
c.JSON(nil, ecode.RequestErr)
return
}
active, err := strconv.ParseInt(p.Get("active"), 10, 64)
if err != nil || (int8(active) != model.FilterActive && int8(active) != model.FilterUnActive) {
c.JSON(nil, ecode.RequestErr)
return
}
if _, err = dmSvc.EditUpFilters(c, id, mid, int8(fType), int8(active)); err != nil {
c.JSON(nil, err)
return
}
c.JSON(nil, nil)
}

View File

@@ -0,0 +1,31 @@
package http
import (
"crypto/md5"
"encoding/hex"
"fmt"
"net/url"
"testing"
)
func TestUpFilters(t *testing.T) {
params := url.Values{}
params.Set("mid", "27515615")
params.Set("type", "3")
params.Set("pn", "1")
params.Set("ps", "5")
mh := md5.Sum([]byte(params.Encode() + "3cf6bd1b0ff671021da5f424fea4b04a"))
params.Set("sign", hex.EncodeToString(mh[:]))
s := managerHost + "/x/admin/dm/upfilter/list?" + params.Encode()
fmt.Println(s)
body, err := oget(s)
if err != nil {
t.Errorf("url(%s) error(%s)", s, err)
t.FailNow()
}
if err = ccode(body); err != nil {
t.Fatal(err, string(body))
t.FailNow()
}
t.Logf("=========%v\n", body)
}

View File

@@ -0,0 +1,134 @@
package http
import (
"net/http"
"go-common/app/admin/main/dm/conf"
"go-common/app/admin/main/dm/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/permit"
"go-common/library/net/http/blademaster/middleware/verify"
)
var (
//dmSvc service
dmSvc *service.Service
verifySvc *verify.Verify
// authSvc auth service
authSvc *permit.Permit
)
// Init http init
func Init(c *conf.Config, s *service.Service) {
dmSvc = s
verifySvc = verify.New(c.Verify)
authSvc = permit.New(c.ManagerAuth)
engine := bm.DefaultServer(c.HTTPServer)
authRouter(engine)
innerRouter(engine)
// init internal server
if err := engine.Start(); err != nil {
log.Error("engine.Start error(%v)", err)
panic(err)
}
}
func authRouter(engine *bm.Engine) {
engine.GET("/monitor/ping", ping)
group := engine.Group("/x/admin/dm")
{
// up filter
group.GET("/upfilter/list", authSvc.Permit("DANMU_POOL_OPERATION"), upFilters)
group.POST("/upfilter/edit", authSvc.Permit("DANMU_POOL_OPERATION"), editUpFilters)
// advance dm list
group.GET("/adv/list", authSvc.Permit("DANMU_POOL_OPERATION"), advList)
// dm transfer
group.GET("/transfer/list", authSvc.Permit("DANMU_POOL_OPERATION"), transferList)
group.POST("/transfer/retry", authSvc.Permit("DANMU_POOL_OPERATION"), reTransferJob)
// dm subject
group.POST("/subject/state/edit", authSvc.Permit("DANMAKU_POOL_SWITCH"), uptSubjectsState)
group.GET("/subject/log", authSvc.Permit("DANMU_LIST"), subjectLog)
group.GET("/subject/archive", authSvc.Permit("DANMU_LIST"), archiveList)
group.POST("/subject/maxlimit", authSvc.Permit("DANMU_POOL_OPERATION"), upSubjectMaxLimit)
// dm mask
group.GET("/mask/state", authSvc.Permit("DANMU_LIST"), maskState)
group.POST("/mask/state/update", authSvc.Permit("DANMAKU_MASK_SWITCH"), updateMaskState)
group.POST("/mask/generate", authSvc.Permit("DANMAKU_MASK_SWITCH"), generateMask)
group.GET("/mask/up", authSvc.Permit("DANMU_LIST"), maskUps)
group.POST("/mask/up/open", authSvc.Permit("DANMAKU_MASK_SWITCH"), maskUpOpen)
// dm task
group.GET("/task/list", authSvc.Permit("DM_TASK_LIST"), taskList)
group.POST("/task/new", authSvc.Permit("DM_TASK_OPERATION"), addTask)
group.POST("/task/review", authSvc.Permit("DM_TASK_REVIEW"), reviewTask)
group.POST("/task/state/edit", authSvc.Permit("DM_TASK_OPERATION"), editTaskState)
group.GET("/task/view", authSvc.Permit("DM_TASK_LIST"), taskView)
group.GET("/task/csv", authSvc.Permit("DM_TASK_LIST"), taskCsv)
// dm list
group.GET("/content/list", authSvc.Permit("DANMU_LIST"), contentList)
group.GET("/report/list/first", authSvc.Permit("DM_REPORT_FIRST_READ"), reportList2)
group.GET("/report/list/second", authSvc.Permit("DM_REPORT_SECOND_READ"), reportList2)
// dm bnj shield
group.POST("/shield/upload", authSvc.Permit("DANMU_LIST"), shieldUpload)
}
subtitleG := group.Group("/subtitle")
{
subtitleG.GET("/list", authSvc.Permit("DM_SUBTITLE"), subtitleList)
subtitleG.POST("/edit", authSvc.Permit("DM_SUBTITLE"), subtitleEdit)
subtitleG.POST("/subject/switch", authSvc.Permit("DM_SUBTITLE"), subtitleSwitch)
}
}
// innerRouter init inner router.
func innerRouter(engine *bm.Engine) {
group := engine.Group("/x/internal/dmadmin", verifySvc.Verify)
{
group.POST("/trans/add", addTrJob)
cg := group.Group("/content")
{
cg.POST("/edit/state", editDMState)
cg.POST("/edit/pool", editDMPool)
cg.POST("/edit/attr", editDMAttr)
cg.GET("/list", dmSearch)
cg.POST("/refresh", xmlCacheFlush)
cg.GET("/index/info", dmIndexInfo)
cg.GET("/log/query", logList)
}
sg := group.Group("/subject")
{
sg.GET("/info", dmIndexInfo)
sg.POST("/fix/count", fixDMCount)
}
rg := group.Group("/report")
{
rg.GET("/list", reportList)
rg.GET("/log", reportLog)
rg.POST("/user/stat/change", changeReportUserStat)
rg.POST("/stat/change", changeReportStat)
rg.POST("/judge", transferJudge)
rg.POST("/judge/result", JudgeResult)
}
mg := group.Group("/monitor")
{
mg.GET("/list", monitorList)
mg.POST("/edit", editMonitor)
}
subtitleG := group.Group("/subtitle")
{
subtitleG.POST("/workflow/callback", subtitleEditCallback)
subtitleG.GET("/workflow/status/list", subtitleStatusList)
subtitleG.GET("/workflow/lans/list", subtitleLanList)
}
}
}
// ping check server state.
func ping(ctx *bm.Context) {
if err := dmSvc.Ping(ctx); err != nil {
log.Error("dm admin ping error(%v)", err)
ctx.JSON(nil, err)
ctx.AbortWithStatus(http.StatusServiceUnavailable)
}
ctx.Next()
}

View File

@@ -0,0 +1,752 @@
package http
import (
"bytes"
"crypto/md5"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"strconv"
"testing"
"time"
"go-common/app/admin/main/dm/conf"
)
const (
localHost = "http://127.0.0.1:6311"
host = "http://uat-api.bilibili.co"
managerHost = "http://uat-manager.bilibili.co"
)
var (
_dmList = host + "/x/internal/dmadmin/content/list"
_refresh = host + "/x/internal/dmadmin/content/refresh"
_editState = host + "/x/internal/dmadmin/content/edit/state"
_editPool = host + "/x/internal/dmadmin/content/edit/pool"
_editAttr = host + "/x/internal/dmadmin/content/edit/attr"
_monitorList = host + "/x/internal/dmadmin/monitor/list"
_editMonitor = host + "/x/internal/dmadmin/monitor/edit"
_dmReportStat = host + "/x/internal/dmadmin/report/stat/change"
_dmReportList = host + "/x/internal/dmadmin/report/list"
_dmReportdetail = host + "/x/internal/dmadmin/report"
_archiveList = localHost + "/x/admin/dm/subject/archive"
_subjectLog = localHost + "/x/admin/dm/subject/log"
_uptSubState = localHost + "/x/admin/dm/subject/state/edit"
_dmSendJudge = host + "/x/internal/dmadmin/report/judge"
_dmJudgeResult = host + "/x/internal/dmadmin/report/judge/result"
_dmIndexInfoURL = host + "/x/internal/dmadmin/content/index/info"
_subjectLimit = host + "/x/admin/dm/subject/maxlimit"
_maskUps = localHost + "/x/admin/dm/mask/up"
_maskUpOpen = localHost + "/x/admin/dm/mask/up/open"
_taskList = managerHost + "/x/admin/dm/task/list"
_taskNew = managerHost + "/x/admin/dm/task/new"
_taskReview = localHost + "/x/admin/dm/task/review"
_taskView = localHost + "/x/admin/dm/task/view"
)
func TestMain(m *testing.M) {
var err error
conf.ConfPath = "../cmd/dm-admin-test.toml"
if err = conf.Init(); err != nil {
panic(err)
}
os.Exit(m.Run())
}
// TestDMList list
func TestDMList(t *testing.T) {
params := url.Values{}
params.Set("type", "1")
params.Set("oid", "10108994")
params.Set("keyword", "哈哈")
params.Set("page_size", "1")
params.Set("appkey", "f6433799dbd88751")
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
mh := md5.Sum([]byte(params.Encode() + "36f8ddb1806207fe07013ab6a77a3935"))
params.Set("sign", hex.EncodeToString(mh[:]))
s := _dmList + "?" + params.Encode()
fmt.Println(s)
body, err := oget(s)
if err != nil {
t.Errorf("url(%s) error(%s)", s, err)
t.FailNow()
}
if err = ccode(body); err != nil {
t.Fatal(err, string(body))
t.FailNow()
}
fmt.Println(string(body))
}
// TestRefrash refrash
func TestRefresh(t *testing.T) {
params := url.Values{}
params.Set("cid", "8937277")
params.Set("appkey", "f6433799dbd88751")
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
mh := md5.Sum([]byte(params.Encode() + "36f8ddb1806207fe07013ab6a77a3935"))
params.Set("sign", hex.EncodeToString(mh[:]))
url := _refresh + "?" + params.Encode()
t.Log(url)
body, err := opost(url)
if err != nil {
t.Errorf("url(%s) error(%s)", url, err)
t.FailNow()
}
if err = ccode(body); err != nil {
t.Fatal(err, string(body))
t.FailNow()
}
var out bytes.Buffer
if err = json.Indent(&out, body, "", " "); err != nil {
t.Fatal(err)
t.FailNow()
}
fmt.Println(out.String())
}
// TestEditState batch
func TestEditState(t *testing.T) {
params := url.Values{}
params.Set("type", "1")
params.Set("oid", "1222")
params.Set("state", "0")
params.Set("dmids", "719181990,719181991")
params.Set("moral", "1")
params.Set("uname", "test")
params.Set("remark", "测试下")
params.Set("appkey", "f6433799dbd88751")
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
mh := md5.Sum([]byte(params.Encode() + "36f8ddb1806207fe07013ab6a77a3935"))
params.Set("sign", hex.EncodeToString(mh[:]))
url := _editState + "?" + params.Encode()
body, err := opost(url)
if err != nil {
t.Errorf("url(%s) error(%s)", url, err)
t.FailNow()
}
if err = ccode(body); err != nil {
t.Fatal(err, string(body))
t.FailNow()
}
var out bytes.Buffer
if err = json.Indent(&out, body, "", " "); err != nil {
t.Fatal(err)
t.FailNow()
}
fmt.Println(out.String())
}
// TestEditPool batch
func TestEditPool(t *testing.T) {
params := url.Values{}
params.Set("type", "1")
params.Set("oid", "1222")
params.Set("pool", "0")
params.Set("dmids", "719181990,719181991")
params.Set("appkey", "f6433799dbd88751")
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
mh := md5.Sum([]byte(params.Encode() + "36f8ddb1806207fe07013ab6a77a3935"))
params.Set("sign", hex.EncodeToString(mh[:]))
url := _editPool + "?" + params.Encode()
fmt.Println(url)
body, err := opost(url)
if err != nil {
t.Errorf("url(%s) error(%s)", url, err)
t.FailNow()
}
if err = ccode(body); err != nil {
t.Fatal(err, string(body))
t.FailNow()
}
var out bytes.Buffer
if err = json.Indent(&out, body, "", " "); err != nil {
t.Fatal(err)
t.FailNow()
}
fmt.Println(out.String())
}
// TestEditAttr batch
func TestEditAttr(t *testing.T) {
params := url.Values{}
params.Set("type", "1")
params.Set("oid", "1222")
params.Set("attr", "1")
params.Set("dmids", "719181990,719181991")
params.Set("appkey", "f6433799dbd88751")
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
mh := md5.Sum([]byte(params.Encode() + "36f8ddb1806207fe07013ab6a77a3935"))
params.Set("sign", hex.EncodeToString(mh[:]))
url := _editAttr + "?" + params.Encode()
fmt.Println(url)
body, err := opost(url)
if err != nil {
t.Errorf("url(%s) error(%s)", url, err)
t.FailNow()
}
if err = ccode(body); err != nil {
t.Fatal(err, string(body))
t.FailNow()
}
var out bytes.Buffer
if err = json.Indent(&out, body, "", " "); err != nil {
t.Fatal(err)
t.FailNow()
}
fmt.Println(out.String())
}
func TestArchiveList(t *testing.T) {
p := url.Values{}
// p.Set("type", "oid")
// p.Set("id", "1345")
p.Set("sort", "desc")
p.Set("order", "mtime")
requestURL := _archiveList + "?" + p.Encode()
fmt.Println(requestURL)
body, err := oget(requestURL)
fmt.Println(string(body))
if err != nil {
t.Errorf("url(%s) error(%s)", requestURL, err)
t.FailNow()
}
var out bytes.Buffer
if err = json.Indent(&out, body, "", " "); err != nil {
t.Fatal(err)
t.FailNow()
}
fmt.Println(out.String())
}
func TestSubjectLog(t *testing.T) {
p := url.Values{}
p.Set("type", "1")
p.Set("oid", "1221")
requestURL := _subjectLog + "?" + p.Encode()
fmt.Println(requestURL)
body, err := oget(requestURL)
fmt.Println(string(body))
if err != nil {
t.Errorf("url(%s) error(%s)", requestURL, err)
t.FailNow()
}
var out bytes.Buffer
if err = json.Indent(&out, body, "", " "); err != nil {
t.Fatal(err)
t.FailNow()
}
fmt.Println(out.String())
}
func TestUptSubjectsState(t *testing.T) {
p := url.Values{}
p.Set("oids", "1223")
p.Set("state", "1")
requestURL := _uptSubState + "?" + p.Encode()
fmt.Println(requestURL)
body, err := opost(requestURL)
fmt.Println(string(body))
if err != nil {
t.Errorf("url(%s) error(%s)", requestURL, err)
t.FailNow()
}
if err = ccode(body); err != nil {
t.Fatal(err, string(body))
t.FailNow()
}
var out bytes.Buffer
if err = json.Indent(&out, body, "", " "); err != nil {
t.Fatal(err)
t.FailNow()
}
fmt.Println(out.String())
}
func TestReportStatChange(t *testing.T) {
params := url.Values{}
params.Set("ids", "9968618:719923090,719923092,719923093")
params.Set("state", "2")
params.Set("uid", "150781")
params.Set("reason", "1")
params.Set("state", "3")
params.Set("remark", "test")
params.Set("notice", "3")
params.Set("block", "-1")
params.Set("moral", "10")
params.Set("block_reason", "5")
params.Set("uname", "zhanghongwen")
params.Set("appkey", "f6433799dbd88751")
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
mh := md5.Sum([]byte(params.Encode() + "36f8ddb1806207fe07013ab6a77a3935"))
params.Set("sign", hex.EncodeToString(mh[:]))
requestURL := _dmReportStat + "?" + params.Encode()
body, err := opost(requestURL)
if err != nil {
t.Errorf("url(%s) error(%s)", requestURL, err)
t.FailNow()
}
if err = ccode(body); err != nil {
t.Fatal(err, string(body))
t.FailNow()
}
var out bytes.Buffer
if err = json.Indent(&out, body, "", " "); err != nil {
t.Fatal(err)
t.FailNow()
}
fmt.Println(out.String())
}
func TestReportList(t *testing.T) {
params := url.Values{}
params.Set("state", "0,1")
params.Set("up_op", "0")
params.Set("page", "1")
params.Set("tid", "24")
params.Set("aid", "")
params.Set("uid", "")
params.Set("rp_user", "")
params.Set("rp_type", "")
params.Set("start", url.QueryEscape("2017-03-21 00:00:00"))
params.Set("end", url.QueryEscape("2017-05-29 00:00:00"))
params.Set("order", "desc")
params.Set("sort", "rp_time")
params.Set("page_size", "2")
params.Set("appkey", "f6433799dbd88751")
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
mh := md5.Sum([]byte(params.Encode() + "36f8ddb1806207fe07013ab6a77a3935"))
params.Set("sign", hex.EncodeToString(mh[:]))
requestURL := _dmReportList + "?" + params.Encode()
t.Log(requestURL)
body, err := oget(requestURL)
if err != nil {
t.Errorf("url(%s) error(%s)", requestURL, err)
t.FailNow()
}
if err = ccode(body); err != nil {
t.Fatal(err, string(body))
t.FailNow()
}
var out bytes.Buffer
if err = json.Indent(&out, body, "", " "); err != nil {
t.Fatal(err)
t.FailNow()
}
fmt.Println(out.String())
}
func TestReportDetail(t *testing.T) {
params := url.Values{}
params.Set("dmid", "719254592")
params.Set("cid", "10106598")
params.Set("appkey", "f6433799dbd88751")
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
mh := md5.Sum([]byte(params.Encode() + "36f8ddb1806207fe07013ab6a77a3935"))
params.Set("sign", hex.EncodeToString(mh[:]))
requestURL := _dmReportdetail + "?" + params.Encode()
body, err := oget(requestURL)
if err != nil {
t.Errorf("url(%s) error(%s)", requestURL, err)
t.FailNow()
}
if err = ccode(body); err != nil {
t.Fatal(err, string(body))
t.FailNow()
}
var out bytes.Buffer
if err = json.Indent(&out, body, "", " "); err != nil {
t.Fatal(err)
t.FailNow()
}
fmt.Println(out.String())
}
func TestSendJudge(t *testing.T) {
params := url.Values{}
params.Set("ids", "10108441:719925897")
params.Set("uname", "luoxiaofan")
params.Set("appkey", "f6433799dbd88751")
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
mh := md5.Sum([]byte(params.Encode() + "36f8ddb1806207fe07013ab6a77a3935"))
params.Set("sign", hex.EncodeToString(mh[:]))
requestURL := _dmSendJudge + "?" + params.Encode()
t.Log(requestURL)
fmt.Println(requestURL)
body, err := opost(requestURL)
if err != nil {
t.Errorf("url(%s) error(%s)", requestURL, err)
t.FailNow()
}
if err = ccode(body); err != nil {
t.Fatal(err, string(body))
t.FailNow()
}
var out bytes.Buffer
if err = json.Indent(&out, body, "", " "); err != nil {
t.Fatal(err)
t.FailNow()
}
fmt.Println(out.String())
}
func TestJudgeResult(t *testing.T) {
params := url.Values{}
params.Set("cid", "1")
params.Set("dmid", "2")
params.Set("result", "1")
params.Set("appkey", "f6433799dbd88751")
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
mh := md5.Sum([]byte(params.Encode() + "36f8ddb1806207fe07013ab6a77a3935"))
params.Set("sign", hex.EncodeToString(mh[:]))
requestURL := _dmJudgeResult + "?" + params.Encode()
fmt.Println(requestURL)
body, err := opost(requestURL)
if err != nil {
t.Errorf("url(%s) error(%s)", requestURL, err)
t.FailNow()
}
if err = ccode(body); err != nil {
t.Fatal(err, string(body))
t.FailNow()
}
var out bytes.Buffer
if err = json.Indent(&out, body, "", " "); err != nil {
t.Fatal(err)
t.FailNow()
}
fmt.Println(out.String())
}
func TestSubjectLimit(t *testing.T) {
params := url.Values{}
params.Set("cid", "1221")
params.Set("limit", "99")
params.Set("appkey", "f6433799dbd88751")
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
mh := md5.Sum([]byte(params.Encode() + "36f8ddb1806207fe07013ab6a77a3935"))
params.Set("sign", hex.EncodeToString(mh[:]))
requestURL := _subjectLimit + "?" + params.Encode()
fmt.Println(requestURL)
body, err := opost(requestURL)
if err != nil {
t.Errorf("url(%s) error(%s)", requestURL, err)
t.FailNow()
}
if err = ccode(body); err != nil {
t.Fatal(err, string(body))
t.FailNow()
}
var out bytes.Buffer
if err = json.Indent(&out, body, "", " "); err != nil {
t.Fatal(err)
t.FailNow()
}
fmt.Println(out.String())
}
func TestDMIndexInfo(t *testing.T) {
params := url.Values{}
params.Set("cid", "9967205")
params.Set("appkey", "f6433799dbd88751")
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
mh := md5.Sum([]byte(params.Encode() + "36f8ddb1806207fe07013ab6a77a3935"))
params.Set("sign", hex.EncodeToString(mh[:]))
requestURL := _dmIndexInfoURL + "?" + params.Encode()
fmt.Println(requestURL)
body, err := oget(requestURL)
if err != nil {
t.Errorf("url(%s) error(%s)", requestURL, err)
t.FailNow()
}
if err = ccode(body); err != nil {
t.Fatal(err, string(body))
t.FailNow()
}
var out bytes.Buffer
if err = json.Indent(&out, body, "", " "); err != nil {
t.Fatal(err)
t.FailNow()
}
fmt.Println(out.String())
}
func TestAddTrJob(t *testing.T) {
params := url.Values{}
params.Set("cid", "9967205")
params.Set("appkey", "f6433799dbd88751")
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
mh := md5.Sum([]byte(params.Encode() + "36f8ddb1806207fe07013ab6a77a3935"))
params.Set("sign", hex.EncodeToString(mh[:]))
}
func TestMonitorList(t *testing.T) {
params := url.Values{}
params.Set("page", "1")
params.Set("page_size", "5")
params.Set("appkey", "f6433799dbd88751")
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
mh := md5.Sum([]byte(params.Encode() + "36f8ddb1806207fe07013ab6a77a3935"))
params.Set("sign", hex.EncodeToString(mh[:]))
requestURL := _monitorList + "?" + params.Encode()
t.Log(requestURL)
body, err := oget(requestURL)
if err != nil {
t.Errorf("url(%s) error(%s)", requestURL, err)
t.FailNow()
}
if err = ccode(body); err != nil {
t.Fatal(err, string(body))
t.FailNow()
}
var out bytes.Buffer
if err = json.Indent(&out, body, "", " "); err != nil {
t.Fatal(err)
t.FailNow()
}
fmt.Println(out.String())
}
func TestEditMonitor(t *testing.T) {
params := url.Values{}
params.Set("type", "1")
params.Set("oids", "1221,1222")
params.Set("state", "1")
params.Set("appkey", "f6433799dbd88751")
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
mh := md5.Sum([]byte(params.Encode() + "36f8ddb1806207fe07013ab6a77a3935"))
params.Set("sign", hex.EncodeToString(mh[:]))
requestURL := _editMonitor + "?" + params.Encode()
t.Log(requestURL)
body, err := opost(requestURL)
if err != nil {
t.Errorf("url(%s) error(%s)", requestURL, err)
t.FailNow()
}
if err = ccode(body); err != nil {
t.Fatal(err, string(body))
t.FailNow()
}
var out bytes.Buffer
if err = json.Indent(&out, body, "", " "); err != nil {
t.Fatal(err)
t.FailNow()
}
fmt.Println(out.String())
}
func TestTransferList(t *testing.T) {
params := url.Values{}
params.Set("cid", "10108682")
params.Set("state", "1")
params.Set("appkey", "53e2fa226f5ad348")
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
mh := md5.Sum([]byte(params.Encode() + "3cf6bd1b0ff671021da5f424fea4b04a"))
params.Set("sign", hex.EncodeToString(mh[:]))
s := managerHost + "/x/admin/dm/transfer/list?" + params.Encode()
fmt.Println(s)
body, err := oget(s)
if err != nil {
t.Errorf("url(%s) error(%s)", s, err)
t.FailNow()
}
if err = ccode(body); err != nil {
t.Fatal(err, string(body))
t.FailNow()
}
//t.Logf("===========%v", body)
}
func TestReTransferJob(t *testing.T) {
params := url.Values{}
params.Set("id", "265")
params.Set("mid", "1")
s := managerHost + "/x/admin/dm/transfer/retry?" + params.Encode()
t.Log(s)
body, err := cpost(s)
if err != nil {
t.Errorf("url(%s) error(%s)", s, err)
t.FailNow()
}
if err = ccode(body); err != nil {
t.Fatal(err, string(body))
t.FailNow()
}
fmt.Println(string(body))
}
func TestMaskUps(t *testing.T) {
body, err := oget(_maskUps)
fmt.Println(string(body))
if err != nil {
t.Errorf("url(%s) error(%s)", _maskUps, err)
t.FailNow()
}
var out bytes.Buffer
if err = json.Indent(&out, body, "", " "); err != nil {
t.Fatal(err)
t.FailNow()
}
fmt.Println(out.String())
}
func TestMaskUpOpen(t *testing.T) {
params := url.Values{}
params.Set("mids", "11111")
params.Set("state", "1")
// params.Set("comment", "test")
requestURL := _maskUpOpen + "?" + params.Encode()
fmt.Println(requestURL)
body, err := opost(requestURL)
fmt.Println(string(body))
if err != nil {
t.Errorf("url(%s) error(%s)", _maskUps, err)
t.FailNow()
}
var out bytes.Buffer
if err = json.Indent(&out, body, "", " "); err != nil {
t.Fatal(err)
t.FailNow()
}
fmt.Println(out.String())
}
func TestTaskList(t *testing.T) {
body, err := oget(_taskList)
fmt.Println(string(body))
if err != nil {
t.Errorf("url(%s) error(%s)", _taskList, err)
t.FailNow()
}
var out bytes.Buffer
if err = json.Indent(&out, body, "", " "); err != nil {
t.Fatal(err)
t.FailNow()
}
fmt.Println(out.String())
}
func TestTaskNew(t *testing.T) {
params := url.Values{}
params.Set("title", "test")
params.Set("mids", "1111")
params.Set("start", "2018-11-11 00:00:00")
params.Set("end", "2018-11-12 00:00:00")
requestURL := _taskNew + "?" + params.Encode()
body, err := cpost(requestURL)
fmt.Println(string(body))
if err != nil {
t.Errorf("url(%s) error(%s)", _taskNew, err)
t.FailNow()
}
var out bytes.Buffer
if err = json.Indent(&out, body, "", " "); err != nil {
t.Fatal(err)
t.FailNow()
}
fmt.Println(out.String())
}
func TestTaskReview(t *testing.T) {
params := url.Values{}
params.Set("id", "15")
params.Set("state", "1")
requestURL := _taskReview + "?" + params.Encode()
body, err := opost(requestURL)
fmt.Println(string(body))
if err != nil {
t.Errorf("url(%s) error(%s)", _taskNew, err)
t.FailNow()
}
var out bytes.Buffer
if err = json.Indent(&out, body, "", " "); err != nil {
t.Fatal(err)
t.FailNow()
}
fmt.Println(out.String())
}
func TestTaskView(t *testing.T) {
params := url.Values{}
params.Set("id", "14")
requestURL := _taskView + "?" + params.Encode()
body, err := oget(requestURL)
fmt.Println(string(body))
if err != nil {
t.Errorf("url(%s) error(%s)", _taskNew, err)
t.FailNow()
}
var out bytes.Buffer
if err = json.Indent(&out, body, "", " "); err != nil {
t.Fatal(err)
t.FailNow()
}
fmt.Println(out.String())
}
// oget http get request
func oget(url string) (body []byte, err error) {
resp, err := http.Get(url)
if err != nil {
return
}
defer resp.Body.Close()
body, err = ioutil.ReadAll(resp.Body)
return
}
// ccode check code == 0
func ccode(body []byte) (err error) {
var d interface{}
err = json.Unmarshal(body, d)
if err != nil {
return
}
ma, ok := d.(map[string]interface{})
if !ok {
return
}
code := ma["code"].(int)
if code != 0 {
err = errors.New("code != 0")
return
}
return
}
// opost http post request
func opost(url string) (body []byte, err error) {
resp, err := http.Post(url, "", nil)
if err != nil {
return
}
defer resp.Body.Close()
body, err = ioutil.ReadAll(resp.Body)
return
}
func cpost(url string) (body []byte, err error) {
client := &http.Client{}
req, err := http.NewRequest("POST", url, nil)
if err != nil {
return
}
req.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
req.Header.Add("Accept-Language", "ja,zh-CN;q=0.8,zh;q=0.6")
req.Header.Add("Connection", "keep-alive")
req.Header.Add("Cookie", `uid=1130; username=fengduzhen; mng-bilibili=b4nec4bi6un0l9ftkfsgj59uq1; _AJSESSIONID=0935506167be9a62bd477a9f10bd6021; JSESSIONID=940FB2C9CAE4FD14171A5D632689C6E5; _uuid=FCC1090C-7E26-52E5-2DC6-26D8EE1B830506546infoc; mng-go=d56eabfa9edf138604586d5dee4929273d1f76a00cfcd69278b6264c453bae2e`)
req.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0")
resp, err := client.Do(req)
if err != nil {
return
}
defer resp.Body.Close()
body, err = ioutil.ReadAll(resp.Body)
return
}

View File

@@ -0,0 +1,121 @@
package http
import (
"strconv"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"go-common/library/xstr"
)
func maskState(c *bm.Context) {
var (
p = c.Request.Form
oid, tp int64
err error
)
if oid, err = strconv.ParseInt(p.Get("oid"), 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if tp, err = strconv.ParseInt(p.Get("type"), 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
open, mobile, web, err := dmSvc.MaskState(c, int32(tp), oid)
res := map[string]interface{}{}
res["open"] = open
res["mobile"] = mobile
res["web"] = web
c.JSON(res, err)
}
func updateMaskState(c *bm.Context) {
var (
p = c.Request.Form
oid, tp, plat, state int64
err error
)
if oid, err = strconv.ParseInt(p.Get("oid"), 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if tp, err = strconv.ParseInt(p.Get("type"), 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if plat, err = strconv.ParseInt(p.Get("plat"), 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if state, err = strconv.ParseInt(p.Get("state"), 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
err = dmSvc.UpdateMaskState(c, int32(tp), oid, int8(plat), int32(state))
c.JSON(nil, err)
}
func generateMask(c *bm.Context) {
var (
p = c.Request.Form
oid, tp, plat int64
err error
)
if oid, err = strconv.ParseInt(p.Get("oid"), 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if tp, err = strconv.ParseInt(p.Get("type"), 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if plat, err = strconv.ParseInt(p.Get("plat"), 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
err = dmSvc.GenerateMask(c, int32(tp), oid, int8(plat))
c.JSON(nil, err)
}
func maskUps(c *bm.Context) {
var (
p = c.Request.Form
pn = int64(1)
ps = int64(50)
err error
)
if p.Get("pn") != "" {
if pn, err = strconv.ParseInt(p.Get("pn"), 10, 64); err != nil || pn <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
}
if p.Get("ps") != "" {
if ps, err = strconv.ParseInt(p.Get("ps"), 10, 64); err != nil || ps <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
}
c.JSON(dmSvc.MaskUps(c, pn, ps))
}
func maskUpOpen(c *bm.Context) {
var (
p = c.Request.Form
comment = p.Get("comment")
mids []int64
state int64
err error
)
if mids, err = xstr.SplitInts(p.Get("mids")); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if state, err = strconv.ParseInt(p.Get("state"), 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
err = dmSvc.MaskUpOpen(c, mids, int32(state), comment)
c.JSON(nil, err)
}

View File

@@ -0,0 +1,111 @@
package http
import (
"strconv"
"go-common/app/admin/main/dm/model"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"go-common/library/xstr"
)
func monitorList(c *bm.Context) {
var (
err error
tp = int64(model.SubTypeVideo)
aid, cid, mid, state int64
page, size int64 = 1, 50
params = c.Request.Form
)
if params.Get("type") != "" {
tp, err = strconv.ParseInt(params.Get("type"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
aidStr := params.Get("aid")
if len(aidStr) > 0 {
aid, err = strconv.ParseInt(aidStr, 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
cidStr := params.Get("cid")
if len(cidStr) > 0 {
cid, err = strconv.ParseInt(cidStr, 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
midStr := params.Get("mid")
if len(midStr) > 0 {
mid, err = strconv.ParseInt(midStr, 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
kw := params.Get("keyword")
if params.Get("state") != "" {
state, err = strconv.ParseInt(params.Get("state"), 10, 64)
if err != nil || (int32(state) != model.MonitorBefore && int32(state) != model.MonitorAfter) {
c.JSON(nil, ecode.RequestErr)
return
}
}
pageStr := params.Get("page")
if len(pageStr) > 0 {
page, err = strconv.ParseInt(pageStr, 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
psStr := params.Get("page_size")
if len(psStr) > 0 {
size, err = strconv.ParseInt(psStr, 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
sort := params.Get("sort")
order := params.Get("order")
data, err := dmSvc.MonitorList(c, int32(tp), aid, cid, mid, int32(state), kw, sort, order, page, size)
res := map[string]interface{}{}
res["data"] = data
c.JSONMap(res, err)
}
func editMonitor(c *bm.Context) {
p := c.Request.Form
tp, err := strconv.ParseInt(p.Get("type"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
state, err := strconv.ParseInt(p.Get("state"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if int32(state) != model.MonitorClosed &&
int32(state) != model.MonitorAfter &&
int32(state) != model.MonitorBefore {
c.JSON(nil, ecode.RequestErr)
return
}
oids, err := xstr.SplitInts(p.Get("oids"))
if err != nil || len(oids) == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if _, err = dmSvc.UpdateMonitor(c, int32(tp), oids, int32(state)); err != nil {
c.JSON(nil, err)
return
}
c.JSON(nil, nil)
}

View File

@@ -0,0 +1,344 @@
package http
import (
"net/url"
"strconv"
"strings"
"go-common/app/admin/main/dm/model"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/xstr"
)
// checkState check admin operation.
func checkState(state int8) (ok bool) {
if state != model.StatFirstInit &&
state != model.StatFirstDelete &&
state != model.StatFirstIgnore &&
state != model.StatSecondInit &&
state != model.StatSecondIgnore &&
state != model.StatSecondAutoDelete &&
state != model.StatSecondDelete {
ok = false
} else {
ok = true
}
return
}
func reportList2(c *bm.Context) {
var (
v = new(model.ReportListParams)
)
if err := c.Bind(v); err != nil {
return
}
c.JSON(dmSvc.ReportList2(c, v))
}
func changeReportStat(c *bm.Context) {
var (
reason, notice, block, blockReason, moral int64
cidDmids = map[int64][]int64{}
params = c.Request.Form
data struct {
Affect int64 `json:"affect"`
}
)
uid, err := strconv.ParseInt(params.Get("adminId"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
state, err := strconv.ParseInt(params.Get("state"), 10, 8)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
uname := params.Get("uname")
remark := params.Get("remark")
noticeStr := params.Get("notice")
if noticeStr != "" {
if notice, err = strconv.ParseInt(noticeStr, 10, 8); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
ids := strings.Split(params.Get("ids"), "|")
if len(ids) == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
for _, idStr := range ids {
var (
cid int64
dmids []int64
)
s := strings.Split(idStr, ":")
if len(s) != 2 {
c.JSON(nil, ecode.RequestErr)
return
}
if cid, err = strconv.ParseInt(s[0], 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if dmids, err = xstr.SplitInts(s[1]); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if !checkState(int8(state)) {
c.JSON(nil, ecode.RequestErr)
return
}
cidDmids[cid] = dmids
}
if state == int64(model.StatSecondDelete) || state == int64(model.StatFirstDelete) {
blockStr := params.Get("block")
if blockStr != "" {
if block, err = strconv.ParseInt(blockStr, 10, 8); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
MoralStr := params.Get("moral")
if MoralStr != "" {
if moral, err = strconv.ParseInt(MoralStr, 10, 8); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
blockReasonStr := params.Get("block_reason")
if blockReasonStr != "" {
if blockReason, err = strconv.ParseInt(blockReasonStr, 10, 8); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
reasonStr := params.Get("reason")
if reasonStr != "" {
if reason, err = strconv.ParseInt(reasonStr, 10, 8); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
}
data.Affect, err = dmSvc.ChangeReportStat(c, cidDmids, int8(state), int8(reason), int8(notice), uid, block, blockReason, moral, remark, uname)
if err != nil {
log.Error("dmSvc.ChangeReportStat(id:%+v, uid:%d) error(%v)", cidDmids, uid, err)
c.JSON(nil, err)
}
res := map[string]interface{}{}
res["data"] = data
c.JSONMap(res, err)
}
func reportList(c *bm.Context) {
var (
tid, rpID []int64
rt *model.Report
p = c.Request.Form
start, end, sort, order, keyword string
)
rt = &model.Report{
Aid: -1,
UID: -1,
RpUID: -1,
RpType: -1,
Cid: -1,
}
state, err := xstr.SplitInts(p.Get("state"))
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
upOp, err := xstr.SplitInts(p.Get("up_op"))
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
page, err := strconv.ParseInt(p.Get("page"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
tidStr := p.Get("tid")
if tidStr != "" {
if tid, err = xstr.SplitInts(tidStr); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
aidStr := p.Get("aid")
if aidStr != "" {
if rt.Aid, err = strconv.ParseInt(aidStr, 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
cidStr := p.Get("cid")
if cidStr != "" {
if rt.Cid, err = strconv.ParseInt(cidStr, 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
uidStr := p.Get("uid")
if uidStr != "" {
if rt.UID, err = strconv.ParseInt(uidStr, 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
userStr := p.Get("rp_user")
if userStr != "" {
if rt.RpUID, err = strconv.ParseInt(userStr, 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
typeStr := p.Get("rp_type")
if typeStr != "" {
if rpID, err = xstr.SplitInts(typeStr); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
startStr := p.Get("start")
start, err = url.QueryUnescape(startStr)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
endStr := p.Get("end")
end, err = url.QueryUnescape(endStr)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
pageSizeStr := p.Get("page_size")
var pageSize int64
if pageSizeStr != "" {
if pageSize, err = strconv.ParseInt(pageSizeStr, 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if pageSize > 100 {
pageSize = 100
}
} else {
pageSize = 100
}
// TODO: swap order&sort
order = p.Get("sort")
sort = p.Get("order")
keyword = p.Get("keyword")
rpts, err := dmSvc.ReportList(c, page, pageSize, start, end, order, sort, keyword, tid, rpID, state, upOp, rt)
res := map[string]interface{}{}
res["data"] = rpts
c.JSONMap(res, err)
}
func reportLog(c *bm.Context) {
p := c.Request.Form
dmid, err := strconv.ParseInt(p.Get("dmid"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
data, err := dmSvc.ReportLog(c, dmid)
res := map[string]interface{}{}
res["data"] = data
c.JSONMap(res, err)
}
func changeReportUserStat(c *bm.Context) {
p := c.Request.Form
dmids, err := xstr.SplitInts(p.Get("dmids"))
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
err = dmSvc.ChangeReportUserStat(c, dmids)
c.JSON(nil, err)
}
func transferJudge(c *bm.Context) {
var (
err error
uname string
cidDmids = map[int64][]int64{}
p = c.Request.Form
)
ids := strings.Split(p.Get("ids"), "|")
if len(ids) == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
for _, idStr := range ids {
var (
cid int64
dmids []int64
)
s := strings.Split(idStr, ":")
if len(s) != 2 {
c.JSON(nil, ecode.RequestErr)
return
}
if cid, err = strconv.ParseInt(s[0], 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if dmids, err = xstr.SplitInts(s[1]); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
cidDmids[cid] = dmids
}
uname = p.Get("uname")
uid, err := strconv.ParseInt(p.Get("adminId"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
err = dmSvc.DMReportJudge(c, cidDmids, uid, uname)
c.JSON(nil, err)
}
// JudgeResult post judgement result
func JudgeResult(c *bm.Context) {
p := c.Request.Form
cid, err := strconv.ParseInt(p.Get("cid"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
dmid, err := strconv.ParseInt(p.Get("dmid"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
result, err := strconv.ParseInt(p.Get("result"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
err = dmSvc.JudgeResult(c, cid, dmid, result)
c.JSON(nil, err)
}
func logList(c *bm.Context) {
p := c.Request.Form
dmid, err := strconv.ParseInt(p.Get("dmid"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
data, err := dmSvc.QueryOpLogs(c, dmid)
res := map[string]interface{}{}
res["data"] = data
c.JSONMap(res, err)
}

View File

@@ -0,0 +1,26 @@
package http
import (
"bytes"
"io"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
func shieldUpload(c *bm.Context) {
file, _, err := c.Request.FormFile("file")
if err != nil {
log.Error("shieldUpload.file.illegal,err::%v", err)
c.JSON(nil, ecode.FileNotExists)
return
}
defer file.Close()
buf := new(bytes.Buffer)
if _, err = io.Copy(buf, file); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
c.JSON(nil, dmSvc.DmShield(c, buf.Bytes()))
}

View File

@@ -0,0 +1,142 @@
package http
import (
"strconv"
"go-common/app/admin/main/dm/model"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"go-common/library/xstr"
)
func archiveList(c *bm.Context) {
var (
p = c.Request.Form
req = &model.ArchiveListReq{
Pn: 1,
Ps: 20,
IDType: p.Get("type"),
Sort: "desc",
Order: "mtime",
Page: int64(model.CondIntNil),
Attrs: make([]int64, 0),
State: int64(model.CondIntNil),
}
err error
)
if idStr := p.Get("id"); len(idStr) > 0 {
if req.ID, err = strconv.ParseInt(idStr, 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
if pageStr := p.Get("page"); len(pageStr) > 0 {
if req.Page, err = strconv.ParseInt(pageStr, 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
if attrStr := p.Get("attrs"); len(attrStr) > 0 {
req.Attrs, err = xstr.SplitInts(attrStr)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
if stateStr := p.Get("state"); len(stateStr) > 0 {
req.State, err = strconv.ParseInt(stateStr, 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
if p.Get("sort") != "" {
req.Sort = p.Get("sort")
}
if p.Get("order") != "" {
req.Order = p.Get("order")
}
if pnStr := p.Get("pn"); len(pnStr) > 0 {
req.Pn, err = strconv.ParseInt(pnStr, 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
if psStr := p.Get("ps"); len(psStr) > 0 {
req.Ps, err = strconv.ParseInt(psStr, 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
data, err := dmSvc.ArchiveList(c, req)
c.JSON(data, err)
}
func uptSubjectsState(c *bm.Context) {
var (
uid, _ = c.Get("uid")
uname, _ = c.Get("username")
p = c.Request.Form
comment = p.Get("comment")
)
oids, err := xstr.SplitInts(p.Get("oids"))
if err != nil || len(oids) == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
tp, err := strconv.ParseInt(p.Get("type"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
state, err := strconv.ParseInt(p.Get("state"), 10, 64)
if err != nil || (int32(state) != model.SubStateOpen && int32(state) != model.SubStateClosed) {
c.JSON(nil, ecode.RequestErr)
return
}
err = dmSvc.UptSubjectsState(c, int32(tp), uid.(int64), uname.(string), oids, int32(state), comment)
c.JSON(nil, err)
}
func upSubjectMaxLimit(c *bm.Context) {
var (
tp int64
p = c.Request.Form
cid, maxlimit int64
err error
)
if tp, err = strconv.ParseInt(p.Get("type"), 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if cid, err = strconv.ParseInt(p.Get("cid"), 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if maxlimit, err = strconv.ParseInt(p.Get("limit"), 10, 64); err != nil || maxlimit > 20000 || maxlimit < 0 {
c.JSON(nil, ecode.RequestErr)
return
}
err = dmSvc.UpSubjectMaxLimit(c, int32(tp), cid, maxlimit)
c.JSON(nil, err)
}
func subjectLog(c *bm.Context) {
var (
p = c.Request.Form
oid, tp int64
err error
)
if oid, err = strconv.ParseInt(p.Get("oid"), 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if tp, err = strconv.ParseInt(p.Get("type"), 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
data, err := dmSvc.SubjectLog(c, int32(tp), oid)
c.JSON(data, err)
}

View File

@@ -0,0 +1,64 @@
package http
import (
"go-common/app/admin/main/dm/model"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
)
// subtitleList 字幕后台管理搜索
func subtitleList(c *bm.Context) {
var (
v = new(model.SubtitleArg)
)
if err := c.Bind(v); err != nil {
return
}
c.JSON(dmSvc.SubtitleList(c, v))
}
// subtitleEdit 字幕操作
func subtitleEdit(c *bm.Context) {
var (
v = new(model.EditSubtitleArg)
)
if err := c.Bind(v); err != nil {
return
}
c.JSON(nil, dmSvc.EditSubtitle(c, v))
}
// workflow 回调函数
func subtitleEditCallback(c *bm.Context) {
var (
v = new(model.WorkFlowSubtitleArg)
)
if err := c.BindWith(v, binding.JSON); err != nil {
return
}
c.JSON(nil, dmSvc.WorkFlowEditSubtitle(c, v))
}
// subtitleStatusList 字幕状态列表 给举报使用
func subtitleStatusList(c *bm.Context) {
c.JSON(dmSvc.SubtitleStatusList(c))
}
func subtitleLanList(c *bm.Context) {
c.JSON(dmSvc.SubtitleLanList(c))
}
// subtitleSwitch 字幕开关
func subtitleSwitch(c *bm.Context) {
var (
v = new(struct {
Aid int64 `form:"aid" validate:"required"`
Allow bool `form:"allow"`
Closed bool `form:"closed"`
})
)
if err := c.Bind(v); err != nil {
return
}
c.JSON(nil, dmSvc.SubtitleSwitch(c, v.Aid, v.Allow, v.Closed))
}

View File

@@ -0,0 +1,101 @@
package http
import (
"fmt"
"net"
"net/http"
"strings"
"go-common/app/admin/main/dm/model"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"go-common/library/xstr"
)
func taskList(c *bm.Context) {
v := new(model.TaskListArg)
if err := c.Bind(v); err != nil {
return
}
c.JSON(dmSvc.TaskList(c, v))
}
func addTask(c *bm.Context) {
var (
uname, _ = c.Get("username")
v = new(model.AddTaskArg)
err error
)
if err = c.Bind(v); err != nil {
return
}
if v.Regex == "" && v.Mids == "" && v.IPs == "" && v.Cids == "" && v.KeyWords == "" {
c.JSON(nil, ecode.RequestErr)
return
}
if _, err = xstr.SplitInts(v.Mids); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if _, err = xstr.SplitInts(v.Cids); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if v.IPs != "" {
ips := strings.Split(v.IPs, ",")
for _, ip := range ips {
tmp := net.ParseIP(ip)
if tmp == nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
}
v.Creator = uname.(string)
c.JSON(nil, dmSvc.AddTask(c, v))
}
func editTaskState(c *bm.Context) {
v := new(model.EditTasksStateArg)
if err := c.Bind(v); err != nil {
return
}
c.JSON(nil, dmSvc.EditTaskState(c, v))
}
func reviewTask(c *bm.Context) {
var (
reviewer, _ = c.Get("username")
v = new(model.ReviewTaskArg)
)
if err := c.Bind(v); err != nil {
return
}
v.Reviewer = reviewer.(string)
c.JSON(nil, dmSvc.ReviewTask(c, v))
}
func taskView(c *bm.Context) {
v := new(model.TaskViewArg)
if err := c.Bind(v); err != nil {
return
}
c.JSON(dmSvc.TaskView(c, v))
}
func taskCsv(c *bm.Context) {
var (
bs []byte
err error
contentType = "text/csv"
)
v := new(model.TaskCsvArg)
if err = c.Bind(v); err != nil {
return
}
if bs, err = dmSvc.TaskCsv(c, v.ID); err != nil {
c.JSON(nil, err)
return
}
c.Writer.Header().Set("Content-Disposition", fmt.Sprintf("attachment;filename=%v.csv", v.ID))
c.Bytes(http.StatusOK, contentType, bs)
}

View File

@@ -0,0 +1,106 @@
package http
import (
"strconv"
"go-common/app/admin/main/dm/model"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
)
func addTrJob(c *bm.Context) {
var (
state int8
p = c.Request.Form
)
from, err := strconv.ParseInt(p.Get("from"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
to, err := strconv.ParseInt(p.Get("to"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
mid, err := strconv.ParseInt(p.Get("mid"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
offset, err := strconv.ParseFloat(p.Get("offset"), 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
err = dmSvc.AddTransferJob(c, from, to, mid, offset, state)
c.JSON(nil, err)
}
func transferList(c *bm.Context) {
var (
p = c.Request.URL.Query()
pn = int64(1)
ps = int64(50)
state = int64(-1)
)
cid, err := strconv.ParseInt(p.Get("cid"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if p.Get("state") != "" {
if state, err = strconv.ParseInt(p.Get("state"), 10, 64); err != nil || state < -1 || state > 3 {
c.JSON(nil, ecode.RequestErr)
return
}
}
if p.Get("pn") != "" {
if pn, err = strconv.ParseInt(p.Get("pn"), 10, 64); err != nil || pn <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
}
if p.Get("ps") != "" {
if ps, err = strconv.ParseInt(p.Get("ps"), 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
list, total, err := dmSvc.TransferList(c, cid, state, pn, ps)
if err != nil {
c.JSON(nil, err)
return
}
pageInfo := &model.PageInfo{
Num: pn,
Size: ps,
Total: total,
}
data := &model.TransListRes{
Result: list,
Page: pageInfo,
}
c.JSON(data, nil)
}
// reTransferJob retransfer job
func reTransferJob(c *bm.Context) {
p := c.Request.Form
id, err := strconv.ParseInt(p.Get("id"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
mid, err := strconv.ParseInt(p.Get("mid"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
err = dmSvc.ReTransferJob(c, id, mid)
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(nil, nil)
}

View File

@@ -0,0 +1,47 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"action.go",
"advance.go",
"dm.go",
"filter.go",
"monitor.go",
"report.go",
"subject.go",
"subtitle.go",
"subtitle_subject.go",
"task.go",
"transfer.go",
],
importpath = "go-common/app/admin/main/dm/model",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/time: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",
"//app/admin/main/dm/model/oplog:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,18 @@
package model
import (
"encoding/json"
)
// All const variable used in admin
const (
ActFlushDM = "flush"
ActReportDel = "report_del"
)
// Action job msg.
type Action struct {
Oid int64 `json:"oid"`
Action string `json:"action"`
Data json.RawMessage `json:"data"`
}

View File

@@ -0,0 +1,42 @@
package model
// all variable used in advance dm
const (
// mode
AdvSpeMode = "sp" // mode 7
AdvMode = "advance" // mode8 mode9
AdvModeAll = "all"
// type
AdvTypeRequest = "request"
AdvTypeAccept = "accept"
AdvTypeDeny = "deny"
AdvTypeAll = "all"
)
// Advance advance dm list
type Advance struct {
ID int64 `json:"id"` //高级弹幕ID
Type string `json:"bType"` //处理结果
Mode string `json:"mode"` //"sp" or 'advance"
Mid int64 `json:"mid"` //申请人ID
Timestamp int64 `json:"timestamp"` //申请时间
Name string `json:"name"` //申请人昵称
}
// AdvanceRes advance dm list result including page info
type AdvanceRes struct {
Result []*Advance `json:"result"`
Page *PageInfo `json:"page"`
}
// PageInfo page info
type PageInfo struct {
Num int64 `json:"num"`
Size int64 `json:"size"`
Total int64 `json:"total"`
}
// ArgMids advance dm mids
type ArgMids struct {
Mids []int64
}

View File

@@ -0,0 +1,375 @@
package model
import (
"strconv"
"go-common/library/time"
"go-common/library/xstr"
)
//CondIntNil cond int nil
const CondIntNil = -10516
// batch operation deleted code
const (
StatusNormal = iota // 正常弹幕
StatusDelete // 删除弹幕
StatusProtect // 保护弹幕
DMIndexInactive = int8(0)
DMIndexActive = int8(1)
PoolNormal = int32(0) // 普通弹幕池
PoolSubtitle = int32(1) // 字幕弹幕池
PoolSpecial = int32(2) // 特殊弹幕池
AttrProtect = uint(0) // 保护弹幕
StateNormal = int32(0) // 普通状态
StateDelete = int32(1) // 删除状态
StateHide = int32(2) // 隐藏状态
StateBlock = int32(3) // 屏蔽状态
StateFilter = int32(4) // 过滤状态
StateMonitorBefore = int32(5) // 先审后发
StateMonitorAfter = int32(6) // 先发后审
StateSensBlock = int32(7) // 敏感词过滤
StateReportDelete = int32(8) // 举报删除
StateAdminDelete = int32(9) // 后台管理删除
StateUserDelete = int32(10) // 用户删除
StateRptAutoDelete = int32(11) // 举报脚本自动删除
StateTaskDelete = int32(12) // 弹幕任务删除
StateAiDelete = int32(13) // ai删除
DMLogBizID = int(31) // dm日志平台business id
// mask platform
MaskPlatWeb int8 = 0
MaskPlatMbl int8 = 1
MaskPlatAll int8 = 100
)
// StateDesc get a state description
func StateDesc(state int32) (description string) {
switch state {
case StateNormal:
description = "正常弹幕"
case StateDelete:
description = "删除状态"
case StateHide:
description = "隐藏状态"
case StateBlock:
description = "屏蔽状态"
case StateFilter:
description = "过滤状态"
case StateMonitorBefore:
description = "先审后发"
case StateMonitorAfter:
description = "先发后审"
case StateSensBlock:
description = "敏感词过滤"
case StateReportDelete:
description = "举报删除"
case StateAdminDelete:
description = "弹幕管理删除"
case StateUserDelete:
description = "用户删除"
case StateRptAutoDelete:
description = "举报脚本删除"
case StateTaskDelete:
description = "弹幕任务删除"
default:
description = "未知状态"
}
return
}
// DM dm info for new database
type DM struct {
ID int64 `json:"id"`
Type int32 `json:"type"`
Oid int64 `json:"oid"`
Mid int64 `json:"mid"`
Progress int32 `json:"progress"`
Pool int32 `json:"pool"`
Attr int32 `json:"attr"`
State int32 `json:"state"`
Ctime time.Time `json:"ctime"`
Mtime time.Time `json:"mtime"`
Content *Content `json:"content,omitempty"`
ContentSpe *ContentSpecial `json:"content_special,omitempty"`
}
// AttrVal return val of index'attr
func (d *DM) AttrVal(bit uint) int32 {
return (d.Attr >> bit) & int32(1)
}
// AttrSet set val of index'attr
func (d *DM) AttrSet(v int32, bit uint) {
d.Attr = d.Attr&(^(1 << bit)) | (v << bit)
}
// AttrNtoA convert uint to string format,eg:5-->101-->1,3.
func (d *DM) AttrNtoA() string {
if d.Attr == 0 {
return ""
}
var bits []int64
for k, v := range strconv.FormatInt(int64(d.Attr), 2) {
if v == 49 {
bits = append(bits, int64(k+1))
}
}
return xstr.JoinInts(bits)
}
// Content dm content info
type Content struct {
ID int64 `json:"id"`
FontSize int32 `json:"fontsize"`
Color int64 `json:"color"`
Mode int32 `json:"mode"`
IP int64 `json:"ip"`
Plat int32 `json:"plat"`
Msg string `json:"msg"`
Ctime time.Time `json:"ctime"`
Mtime time.Time `json:"mtime"`
}
// ContentSpecial special dm data
type ContentSpecial struct {
ID int64 `json:"id"`
Msg string `json:"msg"`
Ctime time.Time `json:"ctime"`
Mtime time.Time `json:"mtime"`
}
// DMVisible check dm is visible or not.
func DMVisible(state int32) bool {
if state == StateNormal || state == StateHide || state == StateMonitorAfter {
return true
}
return false
}
// SearchDMParams dm search params
type SearchDMParams struct {
Type int32 `form:"type" validate:"required"`
Oid int64 `form:"oid" validate:"required"`
Keyword string `form:"keyword"`
Mid int64 `form:"mid" default:"-10516"`
IP string `form:"ip"`
State string `form:"state"`
Pool string `form:"pool"`
Attrs string `form:"attrs"`
ProgressFrom int64 `form:"progress_from" default:"-10516"`
ProgressTo int64 `form:"progress_to" default:"-10516"`
CtimeFrom int64 `form:"ctime_from" default:"-10516"`
CtimeTo int64 `form:"ctime_to" default:"-10516"`
Page int64 `form:"page" default:"1"`
Size int64 `form:"page_size" default:"100"`
Sort string `form:"sort"`
Order string `form:"order"`
}
// SearchDMData dm meta data from search
type SearchDMData struct {
Order string `json:"order"`
Sort string `json:"sort"`
Result []*struct {
ID int64 `json:"id"`
} `json:"result"`
Page *Page `json:"page"`
}
//SearchDMResult dm list
type SearchDMResult struct {
Total int64 `json:"total"`
Count int64 `json:"count"`
MaxLimit int64 `json:"max_limit"`
Protected int64 `json:"protected"`
Deleted int64 `json:"deleted"`
Page int64 `json:"page"`
Pagesize int64 `json:"pagesize"`
Result []*DMItem `json:"result"`
}
//ListItem dm list item
type ListItem struct {
ID int64 `json:"id"`
CID int64 `json:"cid"`
PoolID int `json:"pool_id"`
Deleted int `json:"deleted"`
UID int64 `json:"uid"`
Uname string `json:"uname"`
IP string `json:"ip"`
Playtime float64 `json:"playtime"`
Model int `json:"model"`
Msg string `json:"msg"`
Fontsize int `json:"fontsize"`
Color string `json:"color"`
Ctime time.Time `json:"ctime"`
}
// DMItem dm list item from new db
type DMItem struct {
IDStr string `json:"id_str"`
ID int64 `json:"id"`
Type int32 `json:"type"`
Oid int64 `json:"oid"`
Mid int64 `json:"mid"`
Pool int32 `json:"pool"`
State int32 `json:"state"`
Attrs string `json:"attrs"`
IP int64 `json:"ip"`
Progress int32 `json:"progress"`
Mode int32 `json:"mode"`
Msg string `json:"msg"`
Fontsize int32 `json:"fontsize"`
Color string `json:"color"`
Ctime time.Time `json:"ctime"`
Uname string `json:"uname"`
}
// DMSubject dm_inid info
type DMSubject struct {
OID int64 `json:"oid"`
Type int32 `json:"type"`
AID int64 `json:"aid"`
MID int64 `json:"uid"`
ACount int64 `json:"count"`
Limit int64 `json:"limit"`
TID int64 `json:"tid"`
TName string `json:"tname"`
State int32 `json:"state"`
ETitle string `json:"ep_title"`
Title string `json:"title"`
CTime time.Time `json:"ctime"`
MTime time.Time `json:"mtime"`
}
//ArchiveResult archive list
type ArchiveResult struct {
ArcLists []*DMSubject `json:"archives"`
Page *Page `json:"page"`
}
//DMIndexInfo dm_inid index info
type DMIndexInfo struct {
CID int64 `json:"dm_inid"`
AID int64 `json:"aid"`
MID int64 `json:"mid"`
UName string `json:"u_name"`
Duration int64 `json:"duration"`
Limit int64 `json:"limit"`
Active int64 `json:"dm_active"`
ETitle string `json:"ep_title"`
Title string `json:"title"`
Cover string `json:"cover"`
CTime int64 `json:"ctime"`
MTime int64 `json:"mtime"`
}
// ArcVideo arc+video info by api
type ArcVideo struct {
Archive *struct {
AID int64 `json:"aid"`
MID int64 `json:"mid"`
TID int64 `json:"tid"`
Title string `json:"title"`
Cover string `json:"cover"`
RjReason string `json:"reject_reason"`
Tag string `json:"tag"`
Duration int64 `json:"duration"`
Copyright int64 `json:"copyright"`
Desc string `json:"desc"`
MissionID int64 `json:"mission_id"`
Attribute int64 `json:"attribute"`
State int64 `json:"state"`
Source string `json:"source"`
NoReprint int64 `json:"no_reprint"`
OrderID int64 `json:"order_id"`
DTime int64 `json:"dtime"`
PTime int64 `json:"ptime"`
CTime int64 `json:"ctime"`
} `json:"archive"`
Videos []*struct {
AID int64 `json:"aid"`
Title string `json:"title"`
Desc string `json:"desc"`
Filename string `json:"filename"`
CID int64 `json:"cid"`
Index int64 `json:"index"`
Status int64 `json:"status"`
FailCode int64 `json:"fail_code"`
XState int64 `json:"xcode_state"`
RjReason string `json:"reject_reason"`
CTime int64 `json:"ctime"`
} `json:"videos"`
}
// ArchiveType archive type info
type ArchiveType struct {
ID int64 `json:"id"`
PID int64 `json:"pid"`
Name string `json:"name"`
Desc string `json:"description"`
}
// ArchiveListReq archive list request
type ArchiveListReq struct {
IDType string
ID int64
Page int64
State int64
Attrs []int64
Pn int64
Ps int64
Sort string
Order string
}
// UptSearchDMState update search dm state
type UptSearchDMState struct {
ID int64 `json:"id"`
Oid int64 `json:"oid"`
Type int32 `json:"type"`
State int32 `json:"state"`
Mtime string `json:"mtime"`
}
// UptSearchDMPool update search dm pool
type UptSearchDMPool struct {
ID int64 `json:"id"`
Oid int64 `json:"oid"`
Type int32 `json:"type"`
Pool int32 `json:"pool"`
Mtime string `json:"mtime"`
}
// UptSearchDMAttr update search dm attr
type UptSearchDMAttr struct {
ID int64 `json:"id"`
Oid int64 `json:"oid"`
Type int32 `json:"type"`
Attr int32 `json:"attr"`
Mtime string `json:"mtime"`
AttrFormat []int64 `json:"attr_format"`
}
// MaskUp mask up info.
type MaskUp struct {
ID int64 `json:"id"`
Mid int64 `json:"mid"`
Name string `json:"name"`
State int32 `json:"state"`
Comment string `json:"comment"`
CTime time.Time `json:"ctime"`
MTime time.Time `json:"mtime"`
}
// MaskUpRes maskUp and page info
type MaskUpRes struct {
Result []*MaskUp `json:"result"`
Page *PageInfo `json:"page"`
}

View File

@@ -0,0 +1,35 @@
package model
import (
"go-common/library/time"
)
// all const variable used in dm filter
const (
FilterUnActive int8 = 0
FilterActive int8 = 1
FilterTypeAll int8 = -1 // 所有类型
FilterTypeText int8 = 0 // 文本类型
FilterTypeRegex int8 = 1 // 正则类型
FilterTypeID int8 = 2 // 用户ID类型
FilterMaxUpText = 500 // up主关键字最大条数
FilterMaxUpReg = 100 // up主正则最大条数
FilterMaxUpID = 1000 // up主黑名单最大条数
)
// UpFilter define a new struct, consistent with table "dm_filter_up_%"
type UpFilter struct {
ID int64 `json:"id"`
Oid int64 `json:"oid"`
Type int8 `json:"type"`
Filter string `json:"filter"`
Ctime time.Time `json:"ctime"`
}
// UpFilterRes return UpFilters and PageInfo
type UpFilterRes struct {
Result []*UpFilter `json:"result"`
Page *PageInfo `json:"page"`
}

View File

@@ -0,0 +1,65 @@
package model
// all const variable used in dm monitor
const (
// 监控状态
MonitorClosed = int32(0)
MonitorBefore = int32(1) // 先审后发
MonitorAfter = int32(2) // 先发后审
)
// MonitorResult dm monitor result
type MonitorResult struct {
Order string `json:"order"`
Sort string `json:"sort"`
Page int64 `json:"page"`
PageSize int64 `json:"pagesize"`
Total int64 `json:"total"`
Result []*Monitor `json:"result"`
}
// Monitor dm monitors
type Monitor struct {
ID int64 `json:"id"`
Type int32 `json:"type"`
Pid int64 `json:"pid"`
Oid int64 `json:"oid"`
State int32 `json:"state"`
MCount int64 `json:"mcount"`
Ctime string `json:"ctime"`
Mtime string `json:"mtime"`
Mid int64 `json:"mid"`
Title string `json:"title"`
Author string `json:"author"`
}
// SearchMonitor dm monitor struct
type SearchMonitor struct {
ID int64 `json:"id"`
Type int32 `json:"type"`
Pid int64 `json:"pid"`
Oid int64 `json:"oid"`
State int32 `json:"state"`
Attr int32 `json:"attr"`
MCount int64 `json:"mcount"`
Ctime string `json:"ctime"`
Mtime string `json:"mtime"`
Mid int64 `json:"mid"`
Title string `json:"title"`
Author string `json:"author"`
}
// Page search page info
type Page struct {
Num int64 `json:"num"`
Size int64 `json:"size"`
Total int64 `json:"total"`
}
// SearchMonitorResult result from search
type SearchMonitorResult struct {
Order string `json:"order"`
Sort string `json:"sort"`
Page *Page `json:"page"`
Result []*SearchMonitor `json:"result"`
}

View File

@@ -0,0 +1,29 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["oplog.go"],
importpath = "go-common/app/admin/main/dm/model/oplog",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = ["//library/log: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,89 @@
package oplog
import (
"go-common/library/log"
)
// Infoc operation log for administrator
type Infoc struct {
Oid int64 `json:"oid"`
Type int32 `json:"type"`
DMIds []int64 `json:"dmids"`
Subject string `json:"subject"`
OriginVal string `json:"origin_val"`
CurrentVal string `json:"current_val"`
OperationTime string `json:"optime"`
OperatorType OperatorType `json:"operator_type"`
Operator int64 `json:"operator"`
Source Source `json:"source"`
Remark string `json:"remark"`
}
// InfocResult data model for infoc type operation log storing in hbase
type InfocResult struct {
Oid string `json:"oid"`
Type string `json:"type"`
Subject string `json:"subject"`
CurrentVal string `json:"current_val"`
OperationTime string `json:"operation_time"`
OperatorType string `json:"operator_type"`
Operator string `json:"operator"`
Source string `json:"source"`
Remark string `json:"remark"`
}
// Source enum integer value
type Source int
// Source enum definition list
const (
_ Source = iota
SourceManager
SourceUp
SourcePlayer
)
// String returns the Source enmu description
func (source Source) String() string {
var text string
switch source {
case SourceManager:
text = "运营后台"
case SourceUp:
text = "创作中心"
case SourcePlayer:
text = "播放器"
default:
log.Warn("String() Unknow Source, warn(%v)")
text = "未知来源"
}
return text
}
// OperatorType enum integer value
type OperatorType int
// OperatorType enum definition list
const (
_ OperatorType = iota
OperatorAdmin
OperatorMember
OperatorSystem
)
// String returns the Source enmu description
func (opType OperatorType) String() string {
var text string
switch opType {
case OperatorAdmin:
text = "管理员"
case OperatorMember:
text = "用户"
case OperatorSystem:
text = "系统"
default:
log.Warn("String() Unknow Source, warn(%v)")
text = "未知来源"
}
return text
}

View File

@@ -0,0 +1,337 @@
package model
import (
"fmt"
"time"
)
// const const var
const (
// up主操作
StatUpperInit = int8(0) // up主未处理
StatUpperIgnore = int8(1) // up主已忽略
StatUpperDelete = int8(2) // up主已删除
// 管理员操作
StatFirstInit = int8(0) // 待一审
StatFirstDelete = int8(1) // 一审删除
StatSecondInit = int8(2) // 待二审
StatSecondDelete = int8(3) // 二审删除
StatSecondIgnore = int8(4) // 二审忽略
StatFirstIgnore = int8(5) // 一审忽略
StatSecondAutoDelete = int8(6) // 二审脚本删除
StatJudgeInit = int8(7) // 风纪委待审(二审)
StatJudgeDelete = int8(8) // 风纪委删除(二审)
StatJudgeIgnore = int8(9) // 风纪委忽略(二审)
// 处理结果通知
NoticeUnsend = int8(0) // 未通知用户
NoticeSend = int8(1) // 已通知用户
// 举报通知状态
NoticeReporter = int8(1)
NoticePoster = int8(2)
NoticeAll = int8(3)
// 举报原因
ReportReasonProhibited = int8(1) // 违禁
ReportReasonPorn = int8(2) // 色情
RptReasonFraud = int8(3) // 赌博诈骗
ReportReasonAttack = int8(4) // 人身攻击
ReportReasonPrivate = int8(5) // 隐私
ReportReasonAd = int8(6) // 广告
ReportReasonWar = int8(7) // 引战
ReportReasonSpoiler = int8(8) // 剧透
ReportReasonMeaningless = int8(9) // 刷屏
ReportReasonUnrelated = int8(10) // 视频不相关
ReportReasonOther = int8(11) // 其他
ReportReasonTeenagers = int8(12) // 青少年不良信息
)
// var const map
var (
RptTemplate = map[string]string{
"del": `您好,您在视频#{%s}{"http://www.bilibili.com/av%d"}中举报的弹幕『%s』已被删除%s原因是『%s』感谢您对bilibili社区秩序的维护哔哩哔哩 (゜-゜)つロ 干杯~`,
"ignore": `您好,非常感谢您的举报,您在视频#{%s}{"http://www.bilibili.com/av%d"}中举报的弹幕『%s』暂未认定为违规内容具体弹幕规范烦请参阅 #{《弹幕礼仪》}{"http://www.bilibili.com/blackboard/help.html#d5"},哔哩哔哩 (゜-゜)つロ 干杯~`,
}
PostTemplate = map[int8]string{
1: `您好,根据用户举报,您在视频#{%s}{"http://www.bilibili.com/av%d"}中的弹幕『%s』已被删除%s原因是『%s』请自觉遵守国家相关法律法规具体弹幕规范烦请参阅#{《弹幕礼仪》}{"http://www.bilibili.com/blackboard/help.html#d5"}bilibili良好的社区氛围需要大家一起维护`,
2: `您好,根据用户举报,您在视频#{%s}{"http://www.bilibili.com/av%d"}中的弹幕『%s』已被删除%s原因是『%s』bilibili倡导平等友善的交流具体弹幕规范烦请参阅#{《弹幕礼仪》}{"http://www.bilibili.com/blackboard/help.html#d5"},良好的社区氛围需要大家一起维护!`,
3: `您好,根据用户举报,您在视频#{%s}{"http://www.bilibili.com/av%d"}中的弹幕『%s』已被删除%s原因是『%s』弹幕是公众场所而非私人场所具体弹幕规范烦请参阅#{《弹幕礼仪》}{"http://www.bilibili.com/blackboard/help.html#d5"},良好的社区氛围需要大家一起维护!`,
4: `您好,根据用户举报,您在视频#{%s}{"http://www.bilibili.com/av%d"}中的弹幕『%s』已被删除%s原因是『%s』bilibili倡导发送与视频相关、有用的弹幕具体弹幕规范烦请参阅#{《弹幕礼仪》}{"http://www.bilibili.com/blackboard/help.html#d5"},良好的社区氛围需要大家一起维护!`,
}
AdminRptReason = map[int8]string{
1: "内容涉及传播不实信息",
2: "内容涉及非法网站信息",
3: "内容涉及怂恿教唆信息",
4: "内容涉及低俗信息",
5: "内容涉及色情",
6: "内容涉及赌博诈骗信息",
7: "内容涉及人身攻击",
8: "内容涉及侵犯他人隐私",
9: "内容涉及垃圾广告",
10: "内容涉及引战",
11: "内容涉及视频剧透",
12: "恶意刷屏",
13: "视频不相关",
14: "其他",
15: "内容涉及违禁相关",
16: "内容不适宜",
17: "内容涉及青少年不良信息",
}
BlockReason = map[int8]string{
4: "发布赌博诈骗信息",
5: "发布违禁相关信息",
6: "发布垃圾广告信息",
7: "发布人身攻击言论",
8: "发布侵犯他人隐私信息",
9: "发布引战言论",
10: "发布剧透信息",
13: "发布色情信息",
14: "发布低俗信息",
17: "发布非法网站信息",
18: "发布传播不实信息",
19: "发布怂恿教唆信息",
20: "恶意刷屏",
24: "发布青少年不良内容",
}
)
// ReportListParams .
type ReportListParams struct {
States []int64 `form:"state,split"`
UpOps []int64 `form:"upop,split"`
Tids []int64 `form:"tid,split"`
Aid int64 `form:"aid"`
Cid int64 `form:"cid"`
UID int64 `form:"uid"`
RpUID int64 `form:"rp_user"`
RpTypes []int64 `form:"rp_type,split"`
Start string `form:"start"`
End string `form:"end"`
Sort string `form:"sort"`
Order string `form:"order"`
Keyword string `form:"keyword"`
Page int32 `form:"page" default:"1"`
PageSize int32 `form:"page_size" default:"100" validate:"max=1000"`
}
// Report dm report struct.
type Report struct {
DidStr string `json:"dmid_str"` // str id
ID int64 `json:"id"`
Did int64 `json:"dmid"` // 弹幕id
Cid int64 `json:"cid"` // 视频的id
Aid int64 `json:"arc_aid"` // 稿件的id
Tid int64 `json:"arc_typeid"` // 稿件的分区id
UID int64 `json:"dm_owner_uid"` // 弹幕发送者的uid
Msg string `json:"dm_msg"` // 弹幕内容
Count int64 `json:"count"` // 被举报次数
Content string `json:"content"` // 举报内容:只有类别其他才有值
UpOP int8 `json:"up_op"` // up主操作状态
State int8 `json:"state"` // 举报状态
RpUID int64 `json:"uid"` // 最后一个举报用户id
RpTime string `json:"rp_time"` // 举报时间
RpType int64 `json:"reason"` // 举报类型
Title string `json:"arc_title"` // 稿件标题
Deleted int64 `json:"dm_deleted"` // 弹幕状态
UPUid int64 `json:"arc_mid"` // up主id
PoolID int64 `json:"pool_id"` // 弹幕池
Model int64 `json:"model"` // 弹幕model
Score int32 `json:"score"` // 举报分
SendTime string `json:"dm_ctime"` // 弹幕发送时间
Ctime string `json:"ctime"` // 插入时间
Mtime string `json:"mtime"` // 更新时间
RptUsers []*ReportUser `json:"user"` // 举报用户列表
}
// ReportMsg report message
type ReportMsg struct {
Aid int64
Uids string
Did int64
Title string
Msg string
State int8
RptReason int8
BlockReason int8
Block int64
}
// ReportJudge report judge
type ReportJudge struct {
AID int64 `json:"aid"`
MID int64 `json:"mid"`
Operator string `json:"operator"`
OperID int64 `json:"oper_id"`
OContent string `json:"origin_content"`
OTitle string `json:"origin_title"`
OType int64 `json:"origin_type"`
OURL string `json:"origin_url"`
ReasonType int64 `json:"reason_type"`
OID int64 `json:"oid"`
RPID int64 `json:"rp_id"`
TagID int64 `json:"tag_id"`
Type int64 `json:"type"`
Page int64 `json:"page"`
BTime int64 `json:"business_time"`
}
// SearchReportResult dm repost list from search
type SearchReportResult struct {
Code int64 `json:"code"`
Order string `json:"order"`
Sort string `json:"sort"`
Page *struct {
Num int64 `json:"num"`
Size int64 `json:"size"`
Total int64 `json:"total"`
} `json:"page"`
Result []*Report `json:"result"`
}
// UptSearchReport update search report
type UptSearchReport struct {
DMid int64 `json:"dmid"`
State int8 `json:"state"`
Ctime string `json:"ctime"`
Mtime string `json:"mtime"`
}
// ReportList dm report list
type ReportList struct {
Code int64 `json:"code"`
Order string `json:"order"`
Page int64 `json:"page"`
PageSize int64 `json:"pagesize"`
PageCount int64 `json:"pagecount"`
Total int64 `json:"total"`
Result []*Report `json:"result"`
}
// ReduceMoral reduce moral
type ReduceMoral struct {
UID int64
Moral int64
Origin int8
Reason int8
ReasonType int8
Operator string
IsNotify int8
Remark string
}
// BlockUser block user
type BlockUser struct {
UID int64
BlockForever int64
BlockTimeLength int64
BlockRemark string
Operator string
OriginType int64
Moral int64
ReasonType int64
OriginTitle string
OriginContent string
OriginURL string
IsNotify int64
}
// ReportUser report user
type ReportUser struct {
ID int64 `json:"id"`
Did int64 `json:"dmid"`
UID int64 `json:"uid"`
Reason int64 `json:"reason"`
State int8 `json:"state"`
Ctime time.Time `json:"ctime"`
Mtime time.Time `json:"mtime"`
}
// ReportLog dm admin log
type ReportLog struct {
ID int64 `json:"id"`
Did int64 `json:"dmid"`
AdminID int64 `json:"admin_id"`
Reason int8 `json:"reason"`
Result int8 `json:"result"`
Remark string `json:"remark"`
Elapsed int64 `json:"elapsed"`
Ctime time.Time `json:"ctime"`
Mtime time.Time `json:"mtime"`
}
// PosterBlockMsg return report msg template by blockReason
func PosterBlockMsg(reason int8) (str string, err error) {
var (
tmplKey int8
)
switch reason {
case 4, 5, 13, 14, 17, 18, 19, 20, 24:
tmplKey = 1
case 6, 9:
tmplKey = 2
case 7, 8, 10, 12:
tmplKey = 3
default:
err = fmt.Errorf("BlockReason %d not exist", reason)
return
}
str = PostTemplate[tmplKey]
return
}
// PosterAdminRptMsg return report msg template by adminRptReason
func PosterAdminRptMsg(reason int8) (str string, err error) {
var (
tmplKey int8
)
switch reason {
case 1, 2, 3, 4, 5, 6, 15, 17:
tmplKey = 1
case 7, 10:
tmplKey = 2
case 8, 9, 11, 12:
tmplKey = 3
case 13, 14, 16:
tmplKey = 4
default:
err = fmt.Errorf("adminRptReason %d not exist", reason)
return
}
str = PostTemplate[tmplKey]
return
}
// RpReasonToJudgeReason 修改弹幕风纪委的理由
func RpReasonToJudgeReason(r int8) (j int8) {
switch r {
case ReportReasonProhibited:
j = 5
case ReportReasonPorn:
j = 13
case RptReasonFraud:
j = 4
case ReportReasonAttack:
j = 7
case ReportReasonPrivate:
j = 8
case ReportReasonAd:
j = 6
case ReportReasonWar:
j = 9
case ReportReasonSpoiler:
j = 10
case ReportReasonMeaningless:
j = 20
}
return
}
// CheckStateBelong check state first or second check
func CheckStateBelong(state int8) string {
if state == StatFirstInit || state == StatFirstDelete || state == StatFirstIgnore {
return "弹幕举报一审"
}
return "弹幕举报二审"
}

View File

@@ -0,0 +1,111 @@
package model
import (
"go-common/library/time"
)
// All const variable used in dm subject
const (
AttrNo = int32(0) // no
AttrYes = int32(1) // yes
SubTypeVideo = int32(1) // 主题类型
SubStateOpen = int32(0) // 主题打开
SubStateClosed = int32(1) // 主题关闭
AttrSubGuest = uint(0) // 允许游客弹幕
AttrSubSpolier = uint(1) // 允许剧透弹幕
AttrSubMission = uint(2) // 允许活动弹幕
AttrSubAdvance = uint(3) // 允许高级弹幕
AttrSubMonitorBefore = uint(4) // 弹幕先审后发
AttrSubMonitorAfter = uint(5) // 弹幕先发后审
AttrSubMaskOpen = uint(6) // 开启蒙版
AttrSubMblMaskReady = uint(7) // 移动端蒙版生产完成
AttrSubWebMaskReady = uint(8) // web端蒙版生产完成
)
// Subject dm_subject
type Subject struct {
ID int64 `json:"id"`
Type int32 `json:"type"`
Oid int64 `json:"oid"`
Pid int64 `json:"pid"`
Mid int64 `json:"mid"`
State int32 `json:"state"`
Attr int32 `json:"attr"`
ACount int64 `json:"acount"`
Count int64 `json:"count"`
MCount int64 `json:"mcount"`
MoveCnt int64 `json:"move_count"`
Maxlimit int64 `json:"maxlimit"`
Childpool int32 `json:"childpool"`
Ctime time.Time `json:"ctime"`
Mtime time.Time `json:"mtime"`
}
// SubjectLog subject log
type SubjectLog struct {
UID int64 `json:"uid"`
Uname string `json:"uname"`
Oid int64 `json:"oid"`
Action string `json:"action"`
Comment string `json:"comment"`
Ctime string `json:"ctime"`
}
// SeasonInfo season info.
type SeasonInfo struct {
Aid int64 `json:"aid"`
Cid int64 `json:"cid"`
Epid int64 `json:"ep_id"`
Ssid int64 `json:"season_id"`
State int64 `json:"is_delete"`
LTitle string `json:"long_title"`
Title string `json:"title"`
}
// SearchSubjectReq search subject request.
type SearchSubjectReq struct {
Oids, Aids, Mids, Attrs []int64
State int64
Pn, Ps int64
Sort, Order string
}
// SearchSubjectResult result from search
type SearchSubjectResult struct {
Page *Page
Result []*struct {
Oid int64 `json:"oid"`
} `json:"result"`
}
// SearchSubjectLog get subject logs
type SearchSubjectLog struct {
Page *Page
Result []*struct {
UID int64 `json:"uid"`
Uname string `json:"uname"`
Oid int64 `json:"oid"`
Action string `json:"action"`
ExtraData string `json:"extra_data"`
Ctime string `json:"ctime"`
}
}
// AttrVal return val of subject'attr
func (s *Subject) AttrVal(bit uint) int32 {
return (s.Attr >> bit) & int32(1)
}
// AttrSet set val of subject'attr
func (s *Subject) AttrSet(v int32, bit uint) {
s.Attr = s.Attr&(^(1 << bit)) | (v << bit)
}
// IsMonitoring check if the subject is monitoring or not.
func (s *Subject) IsMonitoring() bool {
return s.AttrVal(AttrSubMonitorBefore) == AttrYes ||
s.AttrVal(AttrSubMonitorAfter) == AttrYes
}

View File

@@ -0,0 +1,248 @@
package model
import (
"fmt"
)
var (
_upTpl = `由#{%s}{"http://space.bilibili.com/%d"}在您的稿件《#{%s}{"http://www.bilibili.com/video/av%d"}》下创作的%s语言版本的字幕已被管理员流转到%s。《#{查看详情}{"https://member.bilibili.com/v2#/zimu/my-zimu/zimu-editor?aid=%d&cid=%d&subtitleId=%d"}》)`
_userTpl = `您在稿件《#{%s}{"http://www.bilibili.com/video/av%d"}》下创作的%s语言版本的字幕已被管理员流转到%s状态。《#{查看详情}{"https://member.bilibili.com/v2#/zimu/my-zimu/zimu-editor?aid=%d&cid=%d&subtitleId=%d"}》)`
// StatusContent .
StatusContent = map[uint8]string{
uint8(SubtitleStatusDraft): "草稿",
uint8(SubtitleStatusToAudit): "待审核",
uint8(SubtitleStatusAuditBack): "驳回",
uint8(SubtitleStatusRemove): "删除",
uint8(SubtitleStatusPublish): "发布",
uint8(SubtitleStatusManagerBack): "管理员驳回",
uint8(SubtitleStatusManagerRemove): "管理员删除",
}
)
// WorkFlowSubtitleDispose .
const (
WorkFlowSubtitleDisposeManagerBack = int32(2) // 管理员回退
WorkFlowSubtitleDisposeManagerDelete = int32(3) // 管理员删除
)
// SubtitleStatus .
type SubtitleStatus uint8
// SubtitleStatus
const (
SubtitleStatusUnknown SubtitleStatus = iota
SubtitleStatusDraft
SubtitleStatusToAudit
SubtitleStatusAuditBack
SubtitleStatusRemove
SubtitleStatusPublish
SubtitleStatusCheckToAudit
SubtitleStatusCheckPublish
SubtitleStatusManagerBack
SubtitleStatusManagerRemove
)
// WorkFlowSubtitleArg .
type WorkFlowSubtitleArg struct {
Object *WorkFlowObject `json:"object"`
Targets []*WorkFlowTarget `json:"targets"`
}
// WorkFlowObject .
type WorkFlowObject struct {
Ids []int64 `json:"id"`
Business int64 `json:"business"`
Reason string `json:"reason"`
DisposeMode int32 `json:"dispose_mode"`
}
// WorkFlowTarget .
type WorkFlowTarget struct {
ID int64 `json:"id"`
Eid int64 `json:"eid"`
Oid int64 `json:"oid"`
}
// SearchSubtitleResult result from search
type SearchSubtitleResult struct {
Page *Page
Result []*struct {
Oid int64 `json:"oid"`
ID int64 `json:"id"`
} `json:"result"`
}
// SubtitleList .
type SubtitleList struct {
Page *Page `json:"page"`
Subtitles []*SearchSubtitle `json:"subtitles"`
}
// SearchSubtitle .
type SearchSubtitle struct {
ID int64 `json:"subtitle_id"`
Oid int64 `json:"oid"`
Aid int64 `json:"aid"`
ArchiveName string `json:"archive_name"`
VideoName string `json:"video_name"`
AuthorID int64 `json:"author_id"`
Lan string `json:"lan"`
LanDoc string `json:"lan_doc"`
Status uint8 `json:"status"`
IsSign bool `json:"is_sign"`
IsLock bool `json:"is_lock"`
SubtitleURL string `json:"subtitle_url"`
Mtime int64 `json:"mtime"`
}
// SubtitlePub .
type SubtitlePub struct {
Oid int64
Type int32
Lan uint8
SubtitleID int64
IsDelete bool
}
// Subtitle .
type Subtitle struct {
ID int64 `json:"id"`
Oid int64 `json:"oid"`
Type int32 `json:"type"`
Lan uint8 `json:"lan"`
Aid int64 `json:"aid"`
Mid int64 `json:"mid"`
AuthorID int64 `json:"author_id"`
UpMid int64 `json:"up_mid"`
IsSign bool `json:"is_sign"`
IsLock bool `json:"is_lock"`
Status SubtitleStatus `json:"status"`
PubTime int64 `json:"-"`
SubtitleURL string `json:"subtitle_url"`
Mtime int64 `json:"mtime"`
}
// SubtitleSearchArg .
type SubtitleSearchArg struct {
Aid int64
Oid int64
Mid int64
UpperMid int64
Status uint8
Lan uint8
Ps int32
Pn int32
}
// SubtitleArg .
type SubtitleArg struct {
Aid int64 `form:"aid"`
Oid int64 `form:"oid"`
Mid int64 `form:"mid"`
UpperMid int64 `form:"up_mid"`
Status uint8 `form:"status"`
Lan string `form:"lan"`
Ps int32 `form:"ps" validate:"required"`
Pn int32 `form:"pn" validate:"required"`
}
// EditSubtitleArg .
type EditSubtitleArg struct {
Oid int64 `form:"oid" validate:"required"`
SubtileID int64 `form:"subtitle_id" validate:"required"`
Status uint8 `form:"status"`
NotifyAuthor bool `form:"notify_author"`
NotifyUpper bool `form:"notify_upper"`
}
// SubtitleContext .
type SubtitleContext struct {
// UpdateStatus bool // 更新状态 无事务
DraftCache bool // 删除草稿缓存
SubtitleCache bool // 删除字幕个体缓存 (必须)
RebuildPub bool // 触发到发布状态
CheckHasDraft bool // 处罚到草稿状态
}
// Build .
func (sc *SubtitleContext) Build(origin, dst SubtitleStatus) {
sc.SubtitleCache = true
switch origin {
case SubtitleStatusDraft, SubtitleStatusToAudit:
sc.DraftCache = true
case SubtitleStatusPublish:
sc.RebuildPub = true
}
switch dst {
case SubtitleStatusDraft, SubtitleStatusToAudit:
sc.CheckHasDraft = true
case SubtitleStatusPublish:
sc.RebuildPub = true
}
}
// SubtitleLans .
type SubtitleLans []*SubtitleLan
// SubtitleLan .
type SubtitleLan struct {
Code int64 `json:"code"`
Lan string `json:"lan"`
DocZh string `json:"doc_zh"`
DocEn string `json:"-"`
}
// GetByLan .
func (ss SubtitleLans) GetByLan(lan string) (code int64) {
for _, s := range ss {
if s.Lan == lan {
return s.Code
}
}
return 0
}
// GetByID .
func (ss SubtitleLans) GetByID(lanID int64) (lan string, doc string) {
for _, s := range ss {
if s.Code == lanID {
return s.Lan, s.DocZh
}
}
return
}
// NotifySubtitleUser .
type NotifySubtitleUser struct {
Mid int64
Aid int64
Oid int64
SubtitleID int64
ArchiveName string
LanDoc string
Status string
}
// NotifySubtitleUp .
type NotifySubtitleUp struct {
Mid int64
AuthorID int64
AuthorName string
Aid int64
Oid int64
SubtitleID int64
ArchiveName string
LanDoc string
Status string
}
// Msg .
func (ns *NotifySubtitleUp) Msg() string {
return fmt.Sprintf(_upTpl, ns.AuthorName, ns.AuthorID, ns.ArchiveName, ns.Aid, ns.LanDoc, ns.Status, ns.Aid, ns.Oid, ns.SubtitleID)
}
// Msg .
func (ns *NotifySubtitleUser) Msg() string {
return fmt.Sprintf(_userTpl, ns.ArchiveName, ns.Aid, ns.LanDoc, ns.Status, ns.Aid, ns.Oid, ns.SubtitleID)
}

View File

@@ -0,0 +1,24 @@
package model
// Subtitle state
const (
AttrSubtitleClose = uint(1) // 关闭稿件字幕
)
// SubtitleSubject .
type SubtitleSubject struct {
Aid int64 `json:"aid"`
Allow bool `json:"allow"`
Attr int32 `json:"attr"`
Lan uint8 `json:"lan"`
}
// AttrVal return val of subtitle subject'attr
func (s *SubtitleSubject) AttrVal(bit uint) int32 {
return (s.Attr >> bit) & int32(1)
}
// AttrSet set val of subtitle subject'attr
func (s *SubtitleSubject) AttrSet(v int32, bit uint) {
s.Attr = s.Attr&(^(1 << bit)) | (v << bit)
}

View File

@@ -0,0 +1,113 @@
package model
// TaskStateJump dm task jump a queue
const (
TaskRegexLen = 250 // dm task regex max length
// dm task state
TaskReviewPass = int32(2)
TaskStateRun = int32(3)
TaskStateFailed = int32(4)
)
// TaskList dm task info list
type TaskList struct {
Page *PageInfo
Result []*TaskInfo `json:"result"`
}
// TaskView .
type TaskView struct {
ID int64 `json:"id"`
Title string `json:"title"`
Creator string `json:"creator"`
Reviewer string `json:"reviewer"`
Regex string `json:"regex"`
KeyWords string `json:"keywords"`
IPs string `json:"ips"`
Mids string `json:"mids"`
Cids string `json:"cids"`
Start string `json:"start"`
End string `json:"end"`
QCount int64 `json:"qcount"` //查询总数
Tcount int64 `json:"tcount"` //删除总数
State int32 `json:"state"`
Result string `json:"-"`
Ctime string `json:"ctime"`
Mtime string `json:"mtime"`
SubTask *SubTask `json:"sub,omitempty"`
}
// SubTask .
type SubTask struct {
ID int64 `json:"id"`
Operation int32 `json:"operation"`
Rate int32 `json:"rate"`
Tcount int64 `json:"tcount"` //删除总数
Start string `json:"start"`
End string `json:"end"`
}
// TaskInfo dm task info
type TaskInfo struct {
ID int64 `json:"id"`
Title string `json:"title"`
Creator string `json:"creator"`
Reviewer string `json:"reviewer"`
State int32 `json:"state"`
Result string `json:"result"`
Ctime string `json:"ctime"`
Mtime string `json:"mtime"`
}
// TaskListArg .
type TaskListArg struct {
Creator string `form:"creator"`
Reviewer string `form:"reviewer"`
Title string `form:"title"`
State int32 `form:"state" default:"-1"`
Ctime string `form:"ctime"`
Pn int64 `form:"pn" default:"1" validate:"gt=0"`
Ps int64 `form:"ps" default:"50" validate:"gt=0"`
}
// AddTaskArg .
type AddTaskArg struct {
Creator string
Title string `form:"title" validate:"required"`
Regex string `form:"regex"`
KeyWords string `form:"keywords"`
IPs string `form:"ips"`
Mids string `form:"mids"`
Cids string `form:"cids"`
Start string `form:"start" validate:"required"`
End string `form:"end" validate:"required"`
State int32 `form:"state" default:"0" validate:"gte=0"`
Operation int32 `form:"operation" default:"-1" `
OpTime string `form:"operation_time"`
OpRate int32 `form:"operation_rate" default:"100" validate:"gt=0"`
}
// ReviewTaskArg .
type ReviewTaskArg struct {
ID int64 `form:"id" validate:"required,gte=0"`
State int32 `form:"state" validate:"required,gte=0"`
Reviewer string
Topic string
}
// EditTasksStateArg .
type EditTasksStateArg struct {
IDs string `form:"ids" validate:"required"`
State int32 `form:"state" validate:"required,gte=0"`
}
// TaskViewArg .
type TaskViewArg struct {
ID int64 `form:"id" validate:"required,gte=0"`
}
// TaskCsvArg .
type TaskCsvArg struct {
ID int64 `form:"id" validate:"required,gte=0"`
}

View File

@@ -0,0 +1,40 @@
package model
import "go-common/library/time"
// all variable used in dm transfer
const (
TransferJobStateAll = int8(-1)
TransferJobStatInit = int8(0)
TransferJobStatFinished = int8(1)
TransferJobStatFailed = int8(2)
TransferJobStatTransfing = int8(3)
)
// TransList transfer list info
type TransList struct {
ID int64 `json:"id"` //弹幕转移ID
From int64 `json:"from"` //来源Cid
To int64 `json:"to"` //目标Cid
State int64 `json:"state"` //弹幕转移状态
Title string `json:"title"` //来源稿件标题
Ctime time.Time `json:"ctime"` //转移开始时间
}
// TransListRes return transfer list and page info
type TransListRes struct {
Result []*TransList `json:"result"`
Page *PageInfo `json:"page"`
}
// TransferJobInfo dm transfer info
type TransferJobInfo struct {
ID int64
FromCID int64
ToCID int64
MID int64
Offset float64
State int8
Ctime time.Time
Mtime time.Time
}

View File

@@ -0,0 +1,92 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"advance_test.go",
"dm_test.go",
"filter_test.go",
"mask_test.go",
"monitor_test.go",
"report_test.go",
"service_test.go",
"subject_test.go",
"task_test.go",
"transfer_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/dm/conf:go_default_library",
"//app/admin/main/dm/model:go_default_library",
"//app/admin/main/dm/model/oplog:go_default_library",
"//library/log:go_default_library",
"//library/queue/databus/report:go_default_library",
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"advance.go",
"dm.go",
"filter.go",
"mask.go",
"monitor.go",
"report.go",
"service.go",
"shield.go",
"subject.go",
"subtitle.go",
"subtitle_status.go",
"subtitle_subject.go",
"task.go",
"transfer.go",
],
importpath = "go-common/app/admin/main/dm/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/dm/conf:go_default_library",
"//app/admin/main/dm/dao:go_default_library",
"//app/admin/main/dm/dao/oplog:go_default_library",
"//app/admin/main/dm/model:go_default_library",
"//app/admin/main/dm/model/oplog:go_default_library",
"//app/service/main/account/api:go_default_library",
"//app/service/main/account/model:go_default_library",
"//app/service/main/archive/api:go_default_library",
"//app/service/main/archive/api/gorpc:go_default_library",
"//app/service/main/archive/model/archive:go_default_library",
"//library/database/sql:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/log/infoc:go_default_library",
"//library/queue/databus/report:go_default_library",
"//library/sync/errgroup:go_default_library",
"//library/sync/pipeline/fanout: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,33 @@
package service
import (
"context"
"go-common/app/admin/main/dm/model"
accountApi "go-common/app/service/main/account/api"
"go-common/library/log"
)
// Advances 高级弹幕列表
func (s *Service) Advances(c context.Context, dmInid int64, typ, mode string, pn, ps int64) (res []*model.Advance, total int64, err error) {
var mids = make([]int64, 0)
if res, total, err = s.dao.Advances(c, dmInid, typ, mode, pn, ps); err != nil {
log.Error("dao.Advances(cid:%d, typ:%s, mode:%s, pn:%d,ps:%d) error(%v)", dmInid, typ, mode, pn, ps, err)
return
}
for _, r := range res {
mids = append(mids, r.Mid)
}
arg := &accountApi.MidsReq{Mids: mids}
uInfos, err := s.accountRPC.Infos3(c, arg)
if err != nil {
log.Error("s.accRPC.Infos3(%v) error(%v)", mids, err)
return
}
for _, r := range res {
if v, ok := uInfos.GetInfos()[r.Mid]; ok {
r.Name = v.Name
}
}
return
}

View File

@@ -0,0 +1,16 @@
package service
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestAdvances(t *testing.T) {
Convey("test adv", t, func() {
res, _, err := svr.Advances(context.TODO(), 27515260, "all", "all", 1, 20)
So(err, ShouldBeNil)
So(res, ShouldNotBeEmpty)
})
}

View File

@@ -0,0 +1,456 @@
package service
import (
"context"
"encoding/json"
"fmt"
"strconv"
"sync"
"go-common/app/admin/main/dm/model"
"go-common/app/admin/main/dm/model/oplog"
accountApi "go-common/app/service/main/account/api"
account "go-common/app/service/main/account/model"
"go-common/app/service/main/archive/model/archive"
"go-common/library/log"
"go-common/library/sync/errgroup"
)
const (
_pageSize = 50
)
// dms get dm list from database.
func (s *Service) dms(c context.Context, tp int32, oid int64, dmids []int64) (dms []*model.DM, err error) {
if len(dmids) == 0 {
return
}
contentSpe := make(map[int64]*model.ContentSpecial)
idxMap, special, err := s.dao.IndexsByID(c, tp, oid, dmids)
if err != nil || len(idxMap) == 0 {
return
}
contents, err := s.dao.Contents(c, oid, dmids)
if err != nil {
return
}
if len(special) > 0 {
if contentSpe, err = s.dao.SpecialContents(c, special); err != nil {
return
}
}
for _, content := range contents {
if idx, ok := idxMap[content.ID]; ok {
idx.Content = content
if idx.Pool == model.PoolSpecial {
if _, ok = contentSpe[idx.ID]; ok {
idx.ContentSpe = contentSpe[idx.ID]
}
}
dms = append(dms, idx)
}
}
return
}
// DMSearch danmu list from search.
func (s *Service) DMSearch(c context.Context, p *model.SearchDMParams) (res *model.SearchDMResult, err error) {
var (
mids, dmids []int64
sorted []*model.DM
protectCnt int64
dmMap = make(map[int64]*model.DM)
uidMap = make(map[int64]bool)
)
res = &model.SearchDMResult{}
sub, err := s.dao.Subject(c, p.Type, p.Oid)
if err != nil {
log.Error("s.dao.Subject(%d,%d) error(%v)", p.Type, p.Oid, err)
return
}
if sub == nil {
return
}
srchData, err := s.dao.SearchDM(c, p)
if err != nil {
log.Error("s.dao.SearchDM(%v) error(%v)", p, err)
return
}
if srchData == nil {
return
}
for _, v := range srchData.Result {
dmids = append(dmids, v.ID)
}
dms, err := s.dms(c, p.Type, p.Oid, dmids)
if err != nil {
log.Error("s.dms(%d,%v) error(%v)", p.Oid, dmids, err)
return
}
for _, dm := range dms {
dmMap[dm.ID] = dm
if _, ok := uidMap[dm.Mid]; !ok && dm.Mid > 0 {
uidMap[dm.Mid] = true
mids = append(mids, dm.Mid)
}
}
for _, dmid := range dmids {
if dm, ok := dmMap[dmid]; ok {
sorted = append(sorted, dm)
}
}
total := len(mids)
pageNum := total / _pageSize
if total%_pageSize != 0 {
pageNum++
}
var (
g errgroup.Group
lk sync.Mutex
infoMap = make(map[int64]*account.Info, total)
)
for i := 0; i < pageNum; i++ {
start := i * _pageSize
end := (i + 1) * _pageSize
if end > total {
end = total
}
g.Go(func() (err error) {
var (
arg = &accountApi.MidsReq{Mids: mids[start:end]}
res *accountApi.InfosReply
)
if res, err = s.accountRPC.Infos3(c, arg); err != nil {
log.Error("s.accRPC.Infos3(%v) error(%v)", arg, err)
} else {
for mid, info := range res.GetInfos() {
lk.Lock()
infoMap[mid] = info
lk.Unlock()
}
}
return
})
}
g.Go(func() (err error) {
if protectCnt, err = s.dao.SearchProtectCount(context.TODO(), p.Type, p.Oid); err != nil {
log.Error("s.dao.SearchProtectCount(%d,%d) error(%v)", p.Type, p.Oid, err)
}
return
})
if err = g.Wait(); err != nil {
return
}
for _, dm := range sorted {
msg := dm.Content.Msg
if dm.Pool == model.PoolSpecial && dm.ContentSpe != nil {
msg = dm.ContentSpe.Msg
}
item := &model.DMItem{
IDStr: strconv.FormatInt(dm.ID, 10),
ID: dm.ID,
Type: dm.Type,
Oid: dm.Oid,
Mid: dm.Mid,
Pool: dm.Pool,
State: dm.State,
Attrs: dm.AttrNtoA(),
Msg: msg,
Ctime: dm.Ctime,
Mode: dm.Content.Mode,
IP: dm.Content.IP,
Color: fmt.Sprintf("#%06X", dm.Content.Color),
Progress: dm.Progress,
Fontsize: dm.Content.FontSize,
}
if info, ok := infoMap[dm.Mid]; ok {
item.Uname = info.Name
}
res.Result = append(res.Result, item)
}
res.MaxLimit = sub.Maxlimit
res.Total = sub.ACount
res.Page = srchData.Page.Num
res.Pagesize = srchData.Page.Size
res.Deleted = sub.ACount - sub.Count
res.Protected = protectCnt
res.Count = srchData.Page.Total
return
}
// XMLCacheFlush 刷新弹幕缓存
func (s *Service) XMLCacheFlush(c context.Context, tp int32, oid int64) {
v := make(map[string]interface{})
v["type"] = tp
v["oid"] = oid
v["force"] = true
data, err := json.Marshal(v)
if err != nil {
log.Error("json.Marshal(%v) error(%v)", v, err)
return
}
action := &model.Action{Action: model.ActFlushDM, Data: data, Oid: oid}
s.addAction(action)
}
// EditDMState multi edit dm state.
func (s *Service) EditDMState(c context.Context, tp, state int32, oid int64, reason int8, dmids []int64, moral float64, adminID int64, operator, remark string) (err error) {
if err = s.editDmState(c, tp, state, oid, reason, dmids, moral, adminID, operator, remark); err != nil {
log.Error("s.dao.UpSearchDMState(%d,%d,%v) err (%v)", tp, oid, dmids, err)
return
}
// update dm search index
if err = s.uptSearchDmState(c, tp, state, map[int64][]int64{oid: dmids}); err != nil {
log.Error("s.dao.UpSearchDMState(%d,%d,%v) err (%v)", tp, oid, dmids, err)
}
return
}
// editDmState multi edit dm state.
func (s *Service) editDmState(c context.Context, tp, state int32, oid int64, reason int8, dmids []int64, moral float64, adminID int64, operator, remark string) (err error) {
sub, err := s.dao.Subject(c, tp, oid)
if err != nil || sub == nil {
return
}
dms, err := s.dms(c, tp, oid, dmids)
if err != nil {
return
}
count := countDMNum(dms, state)
affect, err := s.dao.SetStateByIDs(c, tp, oid, dmids, state)
if err != nil || affect == 0 {
return
}
if sub.Count+count < 0 {
count = -sub.Count
}
// update dm_index count
if _, err = s.dao.IncrSubjectCount(c, tp, oid, count); err != nil {
return
}
// write dm admin log
if affect > 0 {
if remark == "" {
remark = model.AdminRptReason[reason]
}
s.OpLog(c, oid, adminID, tp, dmids, "status", "", fmt.Sprint(state), remark, oplog.SourceManager, oplog.OperatorAdmin)
}
// update dm monitor count
if sub.IsMonitoring() {
s.oidLock.Lock()
s.moniOidMap[sub.Oid] = struct{}{}
s.oidLock.Unlock()
}
// flush xml cache
s.XMLCacheFlush(c, tp, oid)
// reduce moral
uidMap := make(map[int64]struct{})
for _, dm := range dms {
if _, ok := uidMap[dm.Mid]; !ok {
uidMap[dm.Mid] = struct{}{}
}
}
if len(uidMap) > 0 && moral > 0 {
for uid := range uidMap {
s.reduceMoral(c, uid, int64(-moral), reason, operator, "弹幕管理")
}
}
return
}
// EditDMPool edit dm pool.
func (s *Service) EditDMPool(c context.Context, tp int32, oid int64, pool int32, dmids []int64, adminID int64) (err error) {
sub, err := s.dao.Subject(c, tp, oid)
if err != nil || sub == nil {
return
}
if sub.Childpool < pool {
if _, err = s.dao.UpSubjectPool(c, tp, oid, pool); err != nil {
return
}
}
affect, err := s.dao.SetPoolIDByIDs(c, tp, oid, pool, dmids)
if err != nil {
return
}
if affect > 0 {
if pool == model.PoolNormal {
s.dao.IncrSubMoveCount(c, tp, oid, -affect) // NOTE update move_count,ignore error
} else {
s.dao.IncrSubMoveCount(c, tp, oid, affect) // NOTE update move_count,ignore error
}
s.OpLog(c, oid, adminID, tp, dmids, "pool", "", fmt.Sprint(pool), "弹幕池变更", oplog.SourceManager, oplog.OperatorAdmin)
}
if err = s.uptSearchDMPool(c, tp, oid, pool, dmids); err != nil {
log.Error("s.dao.UpSearchDMPool(%d,%d,%v) err (%v)", tp, oid, dmids, err)
}
return
}
// EditDMAttr change dm attr
func (s *Service) EditDMAttr(c context.Context, tp int32, oid int64, dmids []int64, bit uint, value int32, adminID int64) (err error) {
var (
eg = errgroup.Group{}
attrMap = make(map[int32][]int64)
)
dms, err := s.dms(c, tp, oid, dmids)
if err != nil {
log.Error("s.dms(oid:%d ids:%v) error(%v)", oid, dmids, err)
return
}
for _, dm := range dms {
dm.AttrSet(value, bit)
attrMap[dm.Attr] = append(attrMap[dm.Attr], dm.ID)
}
for k, v := range attrMap {
attr := k
ids := v
eg.Go(func() (err error) {
affect, err := s.dao.SetAttrByIDs(c, tp, oid, ids, attr)
if err != nil {
log.Error("s.dao.SetAttrByIDs(oid:%d ids:%v) error(%v)", oid, ids, err)
return
}
if affect > 0 {
s.OpLog(c, oid, adminID, tp, ids, "attribute", "", fmt.Sprint(attr), "弹幕保护状态变更", oplog.SourceManager, oplog.OperatorAdmin)
}
if err = s.uptSearchDMAttr(c, tp, oid, attr, dmids); err != nil {
log.Error("dao.UpSearchDMAttr(oid:%d,attr:%d) error(%v)", oid, attr, err)
}
return
})
}
return eg.Wait()
}
// DMIndexInfo get dm index info
func (s *Service) DMIndexInfo(c context.Context, cid int64) (info *model.DMIndexInfo, err error) {
info = new(model.DMIndexInfo)
sub, err := s.dao.Subject(c, model.SubTypeVideo, cid)
if err != nil || sub == nil {
return
}
argAid2 := &archive.ArgAid2{Aid: sub.Pid}
arc, err := s.arcRPC.Archive3(c, argAid2)
if err != nil {
log.Error("s.arcRPC.Archive3(%v) error(%v)", argAid2, err)
err = nil
} else {
info.Title = arc.Title
info.Cover = arc.Pic
}
argVideo := &archive.ArgVideo2{Aid: sub.Pid, Cid: cid}
video, err := s.arcRPC.Video3(c, argVideo)
if err != nil {
log.Error("s.arcRPC.Video3(%v) error(%v)", argVideo, err)
err = nil
} else {
info.Duration = video.Duration
info.ETitle = video.Part
}
argMid := &accountApi.MidReq{Mid: sub.Mid}
uInfo, err := s.accountRPC.Info3(c, argMid)
if err != nil {
log.Error("s.accRPC.Info3(%v) error(%v)", argMid, err)
err = nil
} else {
info.UName = uInfo.GetInfo().GetName()
}
info.AID = sub.Pid
info.CID = sub.Oid
info.MID = sub.Mid
info.Limit = sub.Maxlimit
if sub.State == model.SubStateOpen {
info.Active = 1
} else {
info.Active = 0
}
info.CTime = int64(sub.Ctime)
info.MTime = int64(sub.Mtime)
return
}
// countDMNum count state changed dm count
func countDMNum(dms []*model.DM, state int32) (count int64) {
for _, dm := range dms {
if model.DMVisible(dm.State) && !model.DMVisible(state) {
count--
} else if !model.DMVisible(dm.State) && model.DMVisible(state) {
count++
}
}
return count
}
// FixDMCount fix dm acount,count of aid.
func (s *Service) FixDMCount(c context.Context, aid int64) (err error) {
var (
arg = archive.ArgAid2{Aid: aid}
oids []int64
states = []int64{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} // 弹幕所有状态
normalState = []int64{0, 2, 6} // 前台可能展示的弹幕状态
)
pages, err := s.arcRPC.Page3(c, &arg)
if err != nil {
log.Error("arcRPC.Page3(%v) error(%v)", arg, err)
return
}
if len(pages) == 0 {
log.Warn("aid:%d have no pages", aid)
return
}
for _, page := range pages {
oids = append(oids, page.Cid)
}
subs, err := s.dao.Subjects(c, model.SubTypeVideo, oids)
if err != nil {
return
}
for _, sub := range subs {
tp := sub.Type
oid := sub.Oid
s.cache.Do(c, func(ctx context.Context) {
acount, err := s.dao.DMCount(ctx, tp, oid, states)
if err != nil {
return
}
count, err := s.dao.DMCount(ctx, tp, oid, normalState)
if err != nil {
return
}
s.dao.UpSubjectCount(ctx, tp, oid, acount, count) // 更新新库dm_subject
log.Info("fix dm count,type:%d,oid:%d,acount:%d,count:%d", tp, oid, acount, count)
})
}
return
}
func (s *Service) uptSearchDmState(c context.Context, tp int32, state int32, dmidM map[int64][]int64) (err error) {
if err = s.dao.UpSearchDMState(c, tp, state, dmidM); err != nil {
return
}
if err = s.dao.UpSearchRecentDMState(c, tp, state, dmidM); err != nil {
return
}
return
}
func (s *Service) uptSearchDMPool(c context.Context, tp int32, oid int64, pool int32, dmids []int64) (err error) {
if err = s.dao.UpSearchDMPool(c, tp, oid, pool, dmids); err != nil {
return
}
if err = s.dao.UpSearchRecentDMPool(c, tp, oid, pool, dmids); err != nil {
return
}
return
}
func (s *Service) uptSearchDMAttr(c context.Context, tp int32, oid int64, attr int32, dmids []int64) (err error) {
if err = s.dao.UpSearchDMAttr(c, tp, oid, attr, dmids); err != nil {
return
}
if err = s.dao.UpSearchRecentDMAttr(c, tp, oid, attr, dmids); err != nil {
return
}
return
}

View File

@@ -0,0 +1,72 @@
package service
import (
"context"
"testing"
"go-common/app/admin/main/dm/model"
"github.com/davecgh/go-spew/spew"
. "github.com/smartystreets/goconvey/convey"
)
func TestDMSearch(t *testing.T) {
d := &model.SearchDMParams{
Type: 1,
Oid: 1,
Mid: model.CondIntNil,
ProgressFrom: model.CondIntNil,
ProgressTo: model.CondIntNil,
CtimeFrom: model.CondIntNil,
CtimeTo: model.CondIntNil,
State: "",
Pool: "",
Page: 1,
Order: "id",
Sort: "asc",
}
Convey("test dm list", t, func() {
res, err := svr.DMSearch(context.TODO(), d)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
spew.Dump(res)
So(res.Result, ShouldNotBeEmpty)
})
}
func TestEditDMPool(t *testing.T) {
Convey("test change pool id", t, func() {
err := svr.EditDMPool(context.TODO(), 1, 1, 1, []int64{1, 2}, 123)
So(err, ShouldBeNil)
})
}
func TestXMLCacheFlush(t *testing.T) {
Convey("test flush cache", t, func() {
svr.XMLCacheFlush(context.TODO(), 1, 1221)
})
}
func TestEditDMState(t *testing.T) {
dmids := []int64{1, 2}
Convey("test content status", t, func() {
res := svr.EditDMState(context.TODO(), 1, 1221, 1, 1, dmids, 10, 123, "admin", "test")
So(res, ShouldNotBeNil)
})
}
func TestEditDMAttr(t *testing.T) {
Convey("test change attr", t, func() {
err := svr.EditDMAttr(context.TODO(), 1, 1, []int64{1, 2}, model.AttrProtect, 1, 123)
So(err, ShouldBeNil)
})
}
func TestDMIndexInfo(t *testing.T) {
var cid int64 = 9967205
Convey("test dm index info", t, func() {
idx, err := svr.DMIndexInfo(context.TODO(), cid)
So(err, ShouldBeNil)
So(idx, ShouldNotBeNil)
})
}

View File

@@ -0,0 +1,67 @@
package service
import (
"context"
"go-common/app/admin/main/dm/model"
"go-common/library/log"
)
// UpFilters return up filters
func (s *Service) UpFilters(c context.Context, mid, ftype, pn, ps int64) (res []*model.UpFilter, total int64, err error) {
//type all
if ftype == int64(model.FilterTypeAll) {
if res, total, err = s.dao.UpFiltersAll(c, mid, pn, ps); err != nil {
log.Error("s.dao.UpFiltersAll(mid:%d) error(%v)", mid, err)
}
return
}
if res, total, err = s.dao.UpFilters(c, mid, ftype, pn, ps); err != nil {
log.Error("s.dao.UpFilters(mid:%d, type:%d) error(%v)", mid, ftype, err)
}
return
}
// EditUpFilters edit up filters.
func (s *Service) EditUpFilters(c context.Context, id, mid int64, fType, active int8) (affect int64, err error) {
var limit int
tx, err := s.dao.BeginBiliDMTrans(c)
if err != nil {
log.Error("tx.BeginBiliDMTrans error(%v)", err)
return
}
defer func() {
if err != nil {
if err1 := tx.Rollback(); err1 != nil {
log.Error("tx.Rollback() error(%v)", err1)
}
return
}
if err = tx.Commit(); err != nil {
log.Error("tx.Commit() error(%v)", err)
}
}()
if affect, err = s.dao.UpdateUpFilter(tx, mid, id, active); err != nil {
return
}
switch fType {
case model.FilterTypeText:
limit = model.FilterMaxUpText
case model.FilterTypeRegex:
limit = model.FilterMaxUpReg
case model.FilterTypeID:
limit = model.FilterMaxUpID
}
if active == model.FilterUnActive {
affect = -affect
limit = 10000
}
if _, err = s.dao.UpdateUpFilterCnt(tx, mid, fType, int(affect), limit+1); err != nil {
return
}
s.cache.Do(c, func(ctx context.Context) {
s.dao.DelUpFilterCache(ctx, mid, 0)
})
return
}

View File

@@ -0,0 +1,23 @@
package service
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestUpFilters(t *testing.T) {
Convey("test update user rule", t, func() {
rs, _, err := svr.UpFilters(context.TODO(), 27515615, 1, 1, 20)
So(err, ShouldBeNil)
So(rs, ShouldNotBeEmpty)
})
}
func TestEditUpFilters(t *testing.T) {
Convey("test edit user rule", t, func() {
_, err := svr.EditUpFilters(context.TODO(), 66, 27515256, 1, 0)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,160 @@
package service
import (
"context"
"go-common/app/admin/main/dm/model"
accountApi "go-common/app/service/main/account/api"
"go-common/app/service/main/archive/api"
arcMdl "go-common/app/service/main/archive/model/archive"
"go-common/library/ecode"
"go-common/library/log"
)
// MaskState get mask state
func (s *Service) MaskState(c context.Context, tp int32, oid int64) (open, mobile, web int32, err error) {
sub, err := s.dao.Subject(c, tp, oid)
if err != nil {
return
}
if sub == nil {
err = ecode.ArchiveNotExist
return
}
return sub.AttrVal(model.AttrSubMaskOpen), sub.AttrVal(model.AttrSubMblMaskReady), sub.AttrVal(model.AttrSubWebMaskReady), err
}
// UpdateMaskState update mask state
func (s *Service) UpdateMaskState(c context.Context, tp int32, oid int64, plat int8, state int32) (err error) {
var (
archive3 *api.Arc
err1 error
duration int64
typeID int32
)
sub, err := s.dao.Subject(c, tp, oid)
if err != nil {
return
}
if sub == nil {
err = ecode.ArchiveNotExist
return
}
if archive3, err1 = s.arcRPC.Archive3(c, &arcMdl.ArgAid2{Aid: sub.Pid}); err1 == nil && archive3 != nil {
duration = archive3.Duration
typeID = archive3.TypeID
}
if state == model.AttrYes {
switch plat {
case model.MaskPlatMbl:
if sub.AttrVal(model.AttrSubMblMaskReady) == model.AttrNo {
if err = s.dao.GenerateMask(c, oid, sub.Mid, plat, 0, sub.Pid, duration, typeID); err != nil {
return
}
}
case model.MaskPlatWeb:
if sub.AttrVal(model.AttrSubWebMaskReady) == model.AttrNo {
if err = s.dao.GenerateMask(c, oid, sub.Mid, plat, 0, sub.Pid, duration, typeID); err != nil {
return
}
}
default:
if sub.AttrVal(model.AttrSubMblMaskReady) == model.AttrNo || sub.AttrVal(model.AttrSubWebMaskReady) == model.AttrNo {
if err = s.dao.GenerateMask(c, oid, sub.Mid, plat, 0, sub.Pid, duration, typeID); err != nil {
return
}
}
}
}
sub.AttrSet(state, model.AttrSubMaskOpen)
_, err = s.dao.UpSubjectAttr(c, tp, oid, sub.Attr)
return
}
// GenerateMask generate mask
func (s *Service) GenerateMask(c context.Context, tp int32, oid int64, plat int8) (err error) {
var (
archive3 *api.Arc
err1 error
duration int64
typeID int32
)
sub, err := s.dao.Subject(c, tp, oid)
if err != nil {
return
}
if sub == nil {
err = ecode.ArchiveNotExist
return
}
if archive3, err1 = s.arcRPC.Archive3(c, &arcMdl.ArgAid2{Aid: sub.Pid}); err1 == nil && archive3 != nil {
duration = archive3.Duration
typeID = archive3.TypeID
}
err = s.dao.GenerateMask(c, oid, sub.Mid, plat, 1, sub.Pid, duration, typeID)
return
}
// MaskUps get mask up infos.
func (s *Service) MaskUps(c context.Context, pn, ps int64) (res *model.MaskUpRes, err error) {
MaskUps, total, err := s.dao.MaskUps(c, pn, ps)
if err != nil {
return
}
mids := make([]int64, 0, len(MaskUps))
for _, up := range MaskUps {
mids = append(mids, up.Mid)
}
arg := &accountApi.MidsReq{Mids: mids}
uInfos, err := s.accountRPC.Infos3(c, arg)
if err != nil {
log.Error("s.accRPC.Infos3(%v) error(%v)", mids, err)
return
}
for _, up := range MaskUps {
if info, ok := uInfos.GetInfos()[up.Mid]; ok {
up.Name = info.Name
}
}
res = &model.MaskUpRes{
Result: MaskUps,
Page: &model.PageInfo{
Num: pn,
Size: ps,
Total: total,
},
}
return
}
// MaskUpOpen add mask up
func (s *Service) MaskUpOpen(c context.Context, mids []int64, state int32, comment string) (err error) {
midMap := make(map[int64]struct{})
ids := make([]int64, 0, len(mids))
for _, mid := range mids {
if _, ok := midMap[mid]; !ok {
midMap[mid] = struct{}{}
ids = append(ids, mid)
}
}
// 验证mids
arg := &accountApi.MidsReq{Mids: ids}
uInfos, err := s.accountRPC.Infos3(c, arg)
if err != nil {
log.Error("s.accRPC.Infos3(%v) error(%v)", ids, err)
return
}
if len(uInfos.GetInfos()) < len(ids) {
err = ecode.AccountInexistence
log.Error("s.MaskUpOpen length diff(%d,%d)", len(ids), len(uInfos.GetInfos()))
return
}
for _, id := range ids {
if _, err = s.dao.MaskUpOpen(c, id, state, comment); err != nil {
return
}
}
return
}

View File

@@ -0,0 +1,49 @@
package service
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestMaskState(t *testing.T) {
convey.Convey("mask state", t, func() {
open, mobile, web, err := svr.MaskState(context.TODO(), 1, 1352)
convey.So(err, convey.ShouldBeNil)
t.Logf("===%d,%d,%d", open, mobile, web)
})
}
func TestUpdateMaskState(t *testing.T) {
convey.Convey("open mask", t, func() {
err := svr.UpdateMaskState(context.TODO(), 1, 1352, 1, 0)
convey.So(err, convey.ShouldBeNil)
})
}
func TestGenerateMask(t *testing.T) {
convey.Convey("generate mask", t, func() {
err := svr.GenerateMask(context.TODO(), 1, 1352, 1)
convey.So(err, convey.ShouldBeNil)
})
}
func TestMaskUps(t *testing.T) {
convey.Convey("test mask ups", t, func() {
res, err := svr.MaskUps(context.Background(), 1, 50)
convey.So(err, convey.ShouldBeNil)
convey.So(res, convey.ShouldNotBeNil)
t.Log(res, res.Result, res.Page)
for _, v := range res.Result {
t.Log(v)
}
})
}
func TestMaskUpOpen(t *testing.T) {
convey.Convey("test mask up open", t, func() {
err := svr.MaskUpOpen(context.Background(), []int64{1111, 142341123}, 1, "")
convey.So(err, convey.ShouldBeNil)
})
}

View File

@@ -0,0 +1,109 @@
package service
import (
"context"
"go-common/app/admin/main/dm/model"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/sync/errgroup"
)
// MonitorList get monitor list
func (s *Service) MonitorList(c context.Context, tp int32, pid, oid, mid int64, state int32, kw, sort, order string, page, size int64) (res *model.MonitorResult, err error) {
var attr int32
if state > 0 {
if state == model.MonitorBefore {
attr = int32(model.AttrSubMonitorBefore) + 1
} else {
attr = int32(model.AttrSubMonitorAfter) + 1
}
}
data, err := s.dao.SearchMonitor(c, tp, pid, oid, mid, attr, kw, sort, order, page, size)
if err != nil {
log.Error("dao.SearchMonitor(pid:%d,oid:%d) error(%v)", pid, oid, err)
return
}
res = &model.MonitorResult{
Order: data.Order,
Sort: data.Sort,
Page: data.Page.Num,
PageSize: data.Page.Size,
Total: data.Page.Total,
Result: make([]*model.Monitor, 0, len(data.Result)),
}
for _, v := range data.Result {
m := &model.Monitor{
ID: v.ID,
Type: v.Type,
Pid: v.Pid,
Oid: v.Oid,
MCount: v.MCount,
Ctime: v.Ctime,
Mtime: v.Mtime,
Mid: v.Mid,
Title: v.Title,
Author: v.Author,
}
if v.Attr>>model.AttrSubMonitorBefore&1 == model.AttrYes {
m.State = model.MonitorBefore
} else {
m.State = model.MonitorAfter
}
res.Result = append(res.Result, m)
}
return
}
// UpdateMonitor update monitor state of dm subject.
func (s *Service) UpdateMonitor(c context.Context, tp int32, oids []int64, state int32) (affect int64, err error) {
var wg errgroup.Group
subs, err := s.dao.Subjects(c, tp, oids)
if err != nil {
return
}
for _, v := range subs {
sub := v
switch state {
case model.MonitorClosed:
sub.AttrSet(model.AttrNo, model.AttrSubMonitorBefore)
sub.AttrSet(model.AttrNo, model.AttrSubMonitorAfter)
case model.MonitorBefore:
sub.AttrSet(model.AttrYes, model.AttrSubMonitorBefore)
sub.AttrSet(model.AttrNo, model.AttrSubMonitorAfter)
case model.MonitorAfter:
sub.AttrSet(model.AttrNo, model.AttrSubMonitorBefore)
sub.AttrSet(model.AttrYes, model.AttrSubMonitorAfter)
default:
err = ecode.RequestErr
return
}
wg.Go(func() (err error) {
aft, err := s.dao.UpSubjectAttr(context.TODO(), tp, sub.Oid, sub.Attr)
if err != nil {
return
}
affect = affect + aft
return
})
}
err = wg.Wait()
return
}
// updateMonitorCnt update mcount of subject.
func (s *Service) updateMonitorCnt(c context.Context, sub *model.Subject) (err error) {
var state, mcount int64
if sub.AttrVal(model.AttrSubMonitorBefore) == model.AttrYes {
state = int64(model.StateMonitorBefore)
} else if sub.AttrVal(model.AttrSubMonitorAfter) == model.AttrYes {
state = int64(model.StateMonitorAfter)
} else {
return
}
if mcount, err = s.dao.DMCount(c, sub.Type, sub.Oid, []int64{state}); err != nil {
return
}
_, err = s.dao.UpSubjectMCount(c, sub.Type, sub.Oid, mcount)
return
}

View File

@@ -0,0 +1,38 @@
package service
import (
"context"
"testing"
"go-common/app/admin/main/dm/model"
. "github.com/smartystreets/goconvey/convey"
)
func TestMonitorList(t *testing.T) {
var (
c = context.TODO()
aid, cid, mid, p, ps int64 = 0, 0, 0, 1, 100
kw, sort, order = "", "", ""
state int32 = 1
tp int32 = 1
)
Convey("test monitor list from search", t, func() {
res, err := svr.MonitorList(c, tp, aid, cid, mid, state, kw, sort, order, p, ps)
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
})
}
func TestUpdateMonitor(t *testing.T) {
var (
c = context.TODO()
tp = model.SubTypeVideo
oids = []int64{2, 99}
)
Convey("update dm subject monitor", t, func() {
affect, err := svr.UpdateMonitor(c, tp, oids, 1)
So(affect, ShouldBeGreaterThan, 0)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,663 @@
package service
import (
"bytes"
"context"
"encoding/json"
"fmt"
"math"
"strconv"
"sync"
"time"
"go-common/app/admin/main/dm/dao"
"go-common/app/admin/main/dm/model"
"go-common/app/service/main/archive/api"
"go-common/app/service/main/archive/model/archive"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/sync/errgroup"
)
const (
_searchTimeFormat = "2006-01-02 15:04:05"
)
// ChangeReportStat set dm report status by mult dmid.
func (s *Service) ChangeReportStat(c context.Context, cidDmids map[int64][]int64, state, reason, notice int8, adminID, block, blockReason, moral int64, remark, operator string) (affect int64, err error) {
var (
optDur int64
dmids []int64
dmidList = make([]int64, 0)
nowTime = time.Now()
dmLogMap = make(map[int64][]*model.ReportLog)
rptsMap = make(map[int64]*model.Report)
uptRpts = make([]*model.UptSearchReport, 0)
)
for _, dmids2 := range cidDmids {
dmids = append(dmids, dmids2...)
}
if state == model.StatFirstInit || state == model.StatSecondInit || state == model.StatJudgeInit {
if rptsMap, err = s.reports(c, dmids); err != nil {
log.Error("s.reports(cidDmids:%v) error(%v)", cidDmids, err)
return
}
} else {
if rptsMap, err = s.reportsDetail(c, dmids); err != nil {
log.Error("s.reportsDetail(cidDmids:%v) error(%v)", cidDmids, err)
return
}
}
for cid, dmids := range cidDmids {
if state == model.StatSecondIgnore || state == model.StatFirstIgnore {
if err = s.dao.IgnoreReport(c, cid, dmids, state); err != nil {
log.Error("s.dao.IgnoreReport(cid:%d, dmid:%v) error(%v)", cid, dmids, err)
return 0, err
}
} else {
if err = s.dao.ChangeReportStat(c, cid, dmids, state); err != nil {
log.Error("s.dao.ChangeReportStat(cid:%d, dmid:%v) error(%v)", cid, dmids, err)
return 0, err
}
}
var rpts []*model.Report
if rpts, err = s.dao.Reports(c, cid, dmids); err != nil {
log.Error("s.dao.Reports(cid:%d, dmids:%v) error(%v)", cid, dmids, err)
err = nil
} else {
for _, rpt := range rpts {
var ctime, mtime time.Time
ctime, err = time.Parse(time.RFC3339, rpt.Ctime)
if err != nil {
log.Error("strconv.RarseInt(%s) error(%v)", rpt.Ctime, err)
err = nil
continue
}
mtime, err = time.Parse(time.RFC3339, rpt.Mtime)
if err != nil {
log.Error("strconv.RarseInt(%s) error(%v)", rpt.Mtime, err)
err = nil
continue
}
uptRpt := &model.UptSearchReport{
DMid: rpt.Did,
Ctime: ctime.Format("2006-01-02 15:04:05"),
Mtime: mtime.Format("2006-01-02 15:04:05"),
State: state,
}
uptRpts = append(uptRpts, uptRpt)
}
}
for _, dmid := range dmids {
rpt, ok := rptsMap[dmid]
if !ok {
err = fmt.Errorf("get report detail empty,dmid:%d", dmid)
log.Error("s.ReportsDetail(cid:%d, dmid:%v) error(%v)", cid, dmid, err)
continue
}
if isDeleteOperation(state) {
s.addRptDelAction(rpt)
}
rpt.State = state
var mtime time.Time
if mtime, err = time.ParseInLocation("2006-01-02 15:04:05", rpt.Mtime, time.Local); err == nil {
optDur = int64(time.Since(mtime).Seconds())
}
lg := &model.ReportLog{
Did: dmid,
AdminID: adminID,
Reason: reason,
Result: state,
Remark: remark,
Elapsed: optDur,
Ctime: nowTime,
Mtime: nowTime,
}
dmLogMap[dao.LogTable(rpt.Did)] = append(dmLogMap[dao.LogTable(rpt.Did)], lg)
dmidList = append(dmidList, rpt.Did)
// if moral > 0 {
// s.reduceMoral(c, rpt.UID, moral, reason, uname, fmt.Sprintf("%s, cid:%d, dmid:%d", model.CheckStateBelong(state), cid, dmid))
// }
if block != 0 {
s.blockUser(c, rpt, block, blockReason, moral, operator)
}
if notice == model.NoticeReporter || notice == model.NoticeAll { // 发送邮件给举报方
if len(rpt.RptUsers) > 0 {
s.sendMsgToReporter(c, rpt, block, blockReason, int64(reason))
}
}
if notice == model.NoticePoster || notice == model.NoticeAll {
if len(rpt.RptUsers) > 0 {
s.sendMsgToPoster(c, rpt, block, blockReason, int64(reason))
}
}
}
// if delete or recover this danmu
if isDeleteOperation(state) {
tmpRemark := model.AdminRptReason[reason] + "" + model.BlockReason[int8(blockReason)]
if len(remark) >= 0 {
tmpRemark = remark + "" + tmpRemark
}
// s.dao.SetStateByIDs(c, model.SubTypeVideo, cid, dmids, model.StateReportDelete)
// s.OpLog(c, cid, adminID, 1, dmids, "status", "", fmt.Sprint(model.StateReportDelete), tmpRemark, oplog.SourceManager, oplog.OperatorAdmin)
s.editDmState(c, model.SubTypeVideo, model.StateReportDelete, cid, reason, dmids, float64(moral), adminID, operator, tmpRemark)
}
}
if isDeleteOperation(state) {
// search update ignore error
s.uptSearchDmState(c, model.SubTypeVideo, model.StateReportDelete, cidDmids)
}
if !(state == model.StatSecondInit || state == model.StatFirstInit) {
if err = s.ChangeReportUserStat(c, dmidList); err != nil {
log.Error("s.ChangeReportUserStat(%v) error(%v)", dmidList, err)
}
}
if len(uptRpts) > 0 {
if err = s.dao.UptSearchReport(c, uptRpts); err != nil {
log.Error("s.dao.UpSearchReport(%v) error(%v)", uptRpts, err)
err = nil
}
}
for k, v := range dmLogMap {
if len(v) <= 0 {
continue
}
if err = s.dao.AddReportLog(c, k, v); err != nil {
log.Error("s.dao.AddReportLog(%v) error(%v)", v, err)
return
}
}
return
}
func isDeleteOperation(state int8) bool {
if state == model.StatSecondDelete || state == model.StatFirstDelete || state == model.StatSecondAutoDelete || state == model.StatJudgeDelete {
return true
}
return false
}
func (s *Service) dmState(c context.Context, cidDmids map[int64][]int64) (stateMap map[int64]int64, err error) {
var (
idxMap map[int64]*model.DM
tp = int32(1)
)
stateMap = make(map[int64]int64)
for oid, dmids := range cidDmids {
if idxMap, _, err = s.dao.IndexsByID(c, tp, oid, dmids); err != nil {
log.Error("s.dmState(oid:%v,dmids:%v) err(%v)", oid, dmids, err)
return
}
for dmid, dm := range idxMap {
stateMap[dmid] = int64(dm.State)
}
}
return
}
// ReportList2 .
func (s *Service) ReportList2(c context.Context, params *model.ReportListParams) (rtList *model.ReportList, err error) {
var (
aidMap = make(map[int64]bool)
aids []int64
cidDmids = make(map[int64][]int64)
stateMap = make(map[int64]int64)
)
if params.Start == "" {
now := time.Now()
params.Start = time.Date(now.Year(), now.Month(), now.Day()-3, 0, 0, 0, 0, now.Location()).Format(_searchTimeFormat)
}
if params.End == "" {
now := time.Now()
params.End = time.Date(now.Year(), now.Month(), now.Day()+1, 0, 0, 0, 0, now.Location()).Format(_searchTimeFormat)
}
rptSearch, err := s.dao.SearchReport2(c, params)
if err != nil {
log.Error("s.dao.SearchReport2(params:%+v) error(%v)", params, err)
return
}
for _, v := range rptSearch.Result {
aidMap[v.Aid] = true
cidDmids[v.Cid] = append(cidDmids[v.Cid], v.Did)
}
for aid := range aidMap {
aids = append(aids, aid)
}
archives, err := s.archiveInfos(c, aids)
if err != nil {
log.Error("s.archives(%v) error(%v)", aids, err)
return
}
if stateMap, err = s.dmState(c, cidDmids); err != nil {
return
}
for _, v := range rptSearch.Result {
v.DidStr = strconv.FormatInt(v.Did, 10)
if arc, ok := archives[v.Aid]; ok {
v.Title = arc.Title
}
if state, ok := stateMap[v.Did]; ok {
v.Deleted = state
}
}
rtList = &model.ReportList{
Code: rptSearch.Code,
Order: rptSearch.Order,
Page: rptSearch.Page.Num,
PageSize: rptSearch.Page.Size,
PageCount: (rptSearch.Page.Total-1)/rptSearch.Page.Size + 1,
Total: rptSearch.Page.Total,
Result: rptSearch.Result,
}
return
}
// ReportList get report list from search
func (s *Service) ReportList(c context.Context, page, size int64, start, end, order, sort, keyword string, tid, rpID, state, upOp []int64, rt *model.Report) (rtList *model.ReportList, err error) {
var (
aidMap = make(map[int64]bool)
aids []int64
cidDmids = make(map[int64][]int64)
stateMap = make(map[int64]int64)
)
rptSearch, err := s.dao.SearchReport(c, page, size, start, end, order, sort, keyword, tid, rpID, state, upOp, rt)
if err != nil {
log.Error("s.dao.SearchReport() error(%v)", err)
return
}
for _, v := range rptSearch.Result {
aidMap[v.Aid] = true
cidDmids[v.Cid] = append(cidDmids[v.Cid], v.Did)
}
for aid := range aidMap {
aids = append(aids, aid)
}
archives, err := s.archiveInfos(c, aids)
if err != nil {
log.Error("s.archives(%v) error(%v)", aids, err)
return
}
if stateMap, err = s.dmState(c, cidDmids); err != nil {
return
}
for _, v := range rptSearch.Result {
v.DidStr = strconv.FormatInt(v.Did, 10)
if arc, ok := archives[v.Aid]; ok {
v.Title = arc.Title
}
if state, ok := stateMap[v.Did]; ok {
v.Deleted = state
}
}
rtList = &model.ReportList{
Code: rptSearch.Code,
Order: rptSearch.Order,
Page: rptSearch.Page.Num,
PageSize: rptSearch.Page.Size,
PageCount: (rptSearch.Page.Total-1)/rptSearch.Page.Size + 1,
Total: rptSearch.Page.Total,
Result: rptSearch.Result,
}
return
}
func (s *Service) archiveInfos(c context.Context, aids []int64) (archives map[int64]*api.Arc, err error) {
var (
g errgroup.Group
mu sync.Mutex
l = len(aids)
pagesize = 50
pagenum = int(math.Ceil(float64(l) / float64(pagesize)))
)
archives = make(map[int64]*api.Arc)
for i := 0; i < pagenum; i++ {
start := i * pagesize
end := (i + 1) * pagesize
if end > l {
end = l
}
g.Go(func() (err error) {
arg := &archive.ArgAids2{Aids: aids[start:end]}
res, err := s.arcRPC.Archives3(c, arg)
if err != nil {
log.Error("s.arcRPC.Archives3(%v) error(%v)", arg, err)
return
}
for aid, info := range res {
mu.Lock()
archives[aid] = info
mu.Unlock()
}
return
})
}
err = g.Wait()
return
}
// reportUsers get mult reports users
func (s *Service) reportUsers(c context.Context, dmids []int64) (rptUsers map[int64][]*model.ReportUser, err error) {
var (
g errgroup.Group
mu sync.Mutex
dmidsMap = map[int64][]int64{}
)
for _, dmid := range dmids {
dmidsMap[dao.UserTable(dmid)] = append(dmidsMap[dao.UserTable(dmid)], dmid)
}
rptUsers = make(map[int64][]*model.ReportUser)
for tableID, dmids := range dmidsMap {
key, value := tableID, dmids
g.Go(func() (err error) {
userTmp, err := s.dao.ReportUsers(c, key, value, model.NoticeUnsend)
if err != nil {
return
}
for dmid, users := range userTmp {
mu.Lock()
rptUsers[dmid] = users
mu.Unlock()
}
return
})
}
err = g.Wait()
return
}
// reportsDetail get report list from search and get user list、archive list、dm list.
func (s *Service) reportsDetail(c context.Context, dmids []int64) (res map[int64]*model.Report, err error) {
var (
aidMap = make(map[int64]bool)
aids, dmids2 []int64
)
reports, err := s.reports(c, dmids)
if err != nil {
return
}
for dmid, rpt := range reports {
if _, ok := aidMap[rpt.Aid]; !ok {
aidMap[rpt.Aid] = true
aids = append(aids, rpt.Aid)
}
dmids2 = append(dmids2, dmid)
}
archives, err := s.archiveInfos(c, aids)
if err != nil {
log.Error("s.archives(%v) error(%v)", aids, err)
return nil, err
}
rptUsers, err := s.reportUsers(c, dmids2)
if err != nil {
log.Error("s.rptUsers(%v) error(%v)", dmids2, err)
return nil, err
}
res = make(map[int64]*model.Report)
for dmid, rpt := range reports {
if arc, ok := archives[rpt.Aid]; ok {
rpt.Title = arc.Title
}
if users, ok := rptUsers[dmid]; ok {
rpt.RptUsers = users
} else {
rpt.RptUsers = make([]*model.ReportUser, 0)
}
res[dmid] = rpt
}
return
}
// reports get report list by cid and dmids from search.
func (s *Service) reports(c context.Context, dmids []int64) (res map[int64]*model.Report, err error) {
rptSearchList, err := s.dao.SearchReportByID(c, dmids)
if err != nil || len(rptSearchList.Result) <= 0 {
log.Error("dao.SearchReportByID(ids:%v) error(%v)", dmids, err)
return
}
res = make(map[int64]*model.Report)
for _, rpt := range rptSearchList.Result {
res[rpt.Did] = rpt
}
return
}
// ReportLog get report log by dmid.
func (s *Service) ReportLog(c context.Context, dmid int64) (res []*model.ReportLog, err error) {
if res, err = s.dao.ReportLog(c, dmid); err != nil {
log.Error("s.dao.ReportLog(dmid:%d) error(%v)", dmid, err)
}
return
}
// ChangeReportUserStat change report_user data
func (s *Service) ChangeReportUserStat(c context.Context, dmids []int64) (err error) {
var (
dmidMap = map[int64][]int64{}
)
for _, v := range dmids {
dmidMap[dao.UserTable(v)] = append(dmidMap[dao.UserTable(v)], v)
}
for k, v := range dmidMap {
if _, err = s.dao.UpReportUserState(c, k, v, model.NoticeSend); err != nil {
log.Error("s.dao.UpReportUserState(dmids:%v) error(%v)", v, err)
}
}
return
}
func (s *Service) sendMsgToReporter(c context.Context, rpt *model.Report, block, blockReason, rptReason int64) {
var (
buf bytes.Buffer
)
for _, user := range rpt.RptUsers {
buf.WriteString(fmt.Sprintf("%d,", user.UID))
}
buf.Truncate(buf.Len() - 1)
m := &model.ReportMsg{
Aid: rpt.Aid,
Did: rpt.Did,
Title: rpt.Title,
Msg: rpt.Msg,
RptReason: int8(rptReason),
Uids: buf.String(),
State: rpt.State,
Block: block,
BlockReason: int8(blockReason),
}
select {
case s.msgReporterChan <- m:
default:
log.Error("s.msgReporterChan err, channel full(msg:%v)", m)
}
}
func (s *Service) sendMsgToPoster(c context.Context, rpt *model.Report, block, blockReason, rptReason int64) {
m := &model.ReportMsg{
Aid: rpt.Aid,
Did: rpt.Did,
Title: rpt.Title,
Msg: rpt.Msg,
RptReason: int8(rptReason),
Uids: fmt.Sprint(rpt.UID),
Block: block,
BlockReason: int8(blockReason),
}
select {
case s.msgPosterChan <- m:
default:
log.Error("s.msgPosterChan err, channel full(msg:%v)", m)
}
}
func (s *Service) reduceMoral(c context.Context, uid, moral int64, reason int8, operator, remark string) {
m := &model.ReduceMoral{
UID: uid,
Moral: moral,
Origin: 2,
Reason: reason,
ReasonType: 1,
Operator: operator,
IsNotify: 0,
Remark: remark,
}
select {
case s.reduceMoralChan <- m:
default:
log.Error("s.reduceMoral err, channel full(msg:%v)", m)
}
}
func (s *Service) blockUser(c context.Context, rpt *model.Report, block, blockReason, moral int64, uname string) {
var (
blockEver int64
blockLength int64
)
if block == -1 {
blockEver = 1
} else {
blockLength = block
}
m := &model.BlockUser{
UID: rpt.UID,
BlockForever: blockEver,
BlockTimeLength: blockLength,
BlockRemark: fmt.Sprintf("%s, cid:%d, dmid:%d", model.CheckStateBelong(rpt.State), rpt.Cid, rpt.Did),
Operator: uname,
OriginType: 2,
Moral: moral,
ReasonType: blockReason,
OriginTitle: rpt.Title,
OriginContent: rpt.Msg,
OriginURL: fmt.Sprintf("http://www.bilibili.com/av%d", rpt.Aid),
IsNotify: 0,
}
select {
case s.blockUserChan <- m:
default:
log.Error("s.blockUserChan err, channel full(msg:%v)", m)
}
}
// DMReportJudge send report judge
func (s *Service) DMReportJudge(c context.Context, cidDmids map[int64][]int64, uid int64, uname string) (err error) {
var (
aids []int64
dmids []int64
rptJudges []*model.ReportJudge
)
for _, dmids2 := range cidDmids {
dmids = append(dmids, dmids2...)
}
rpts, err := s.reportsDetail(c, dmids) // get report detail by multi dmids
if len(rpts) == 0 {
log.Error("dmjudge error! id:%v not exist in search", dmids)
return
}
for _, rpt := range rpts {
aids = append(aids, rpt.Aid)
}
arg := &archive.ArgAids2{Aids: aids}
archs, err := s.arcRPC.Archives3(c, arg) // get archive info
if err != nil {
log.Error("s.arcSvc.Archives3(aids:%v) err(%v)", aids, err)
return
}
if len(archs) == 0 {
log.Error("dmjudge error! id:%v not exist in archive rpc", aids)
err = ecode.ArchiveNotExist
return
}
for _, rpt := range rpts {
j := &model.ReportJudge{}
arc, ok := archs[rpt.Aid]
if !ok {
continue
}
arg := &archive.ArgVideo2{
Aid: rpt.Aid,
Cid: rpt.Cid,
}
var vInfo *api.Page
if vInfo, err = s.arcRPC.Video3(c, arg); err != nil {
log.Error("s.arcSvc.Video3(arg:%v) err(%v)", arg, err)
j.Page = 1
} else {
j.Page = int64(vInfo.Page)
}
j.MID = rpt.UID
j.Operator = uname
j.OperID = uid
j.OContent = rpt.Msg
j.OTitle = arc.Title
j.OType = 2
j.OURL = fmt.Sprintf("http://www.bilibili.com/av%d", rpt.Aid)
j.ReasonType = int64(model.RpReasonToJudgeReason(int8(rpt.RpType)))
j.AID = rpt.Aid
j.OID = rpt.Cid
j.RPID = rpt.Did
sendTime, _ := time.Parse("2006-01-02 15:04:05", rpt.SendTime)
j.BTime = sendTime.Unix()
rptJudges = append(rptJudges, j)
}
if len(rptJudges) <= 0 {
return
}
if err = s.dao.SendJudgement(c, rptJudges); err != nil {
log.Error("s.dao.SendJudgement(data:%v) err (%v)", rptJudges, err)
}
_, err = s.ChangeReportStat(c, cidDmids, model.StatJudgeInit, 0, 0, uid, 0, 0, 0, "转风纪委", uname)
if err != nil {
log.Error("s.ChangeReportStat(id:%v) err(%v)", cidDmids, err)
return
}
return
}
// JudgeResult receive judge result
func (s *Service) JudgeResult(c context.Context, cid, dmid, result int64) (err error) {
var (
state int8
remark string
)
res, err := s.dao.Reports(c, cid, []int64{dmid})
if err != nil {
log.Error("s.dao.Reports(cid:%d,dmid:%d) err(%v)", cid, dmid, err)
return
}
if len(res) <= 0 {
log.Error("dmJudge: cid:%d,dmid:%d not found", cid, dmid)
err = ecode.RequestErr
return
}
m := map[int64][]int64{
res[0].Cid: {res[0].Did},
}
if result == 0 {
state = model.StatJudgeIgnore
remark = "风纪委处理:忽略"
} else {
state = model.StatJudgeDelete
remark = "风纪委处理:删除"
}
_, err = s.ChangeReportStat(c, m, state, int8(res[0].RpType), 0, 0, 0, 0, 0, remark, "")
if err != nil {
log.Error("s.ChangeReportStat(cid:%d,dmid:%d) err(%v)", cid, dmid, err)
return
}
return
}
func (s *Service) addRptDelAction(rpt *model.Report) (err error) {
data, err := json.Marshal(rpt)
if err != nil {
log.Error("json.Marshal(%v) error(%v)", rpt, err)
return
}
action := &model.Action{
Oid: rpt.Cid,
Action: model.ActReportDel,
Data: data,
}
s.addAction(action)
return
}

View File

@@ -0,0 +1,94 @@
package service
import (
"context"
"testing"
"go-common/app/admin/main/dm/model"
. "github.com/smartystreets/goconvey/convey"
)
func TestChangeReportStat(t *testing.T) {
var (
c = context.TODO()
cidDmids = map[int64][]int64{
9968618: {
719923090, 719923092,
},
}
state = model.StatSecondDelete
reason int8 = 2
notice int8 = 3
adminID int64 = 222
remark = "二审删除"
block int64 = 3
blockReason int64
moral int64 = 10
uname = "zzz delete"
)
Convey("test change report stat", t, func() {
affect, err := svr.ChangeReportStat(c, cidDmids, state, reason, notice, adminID, block, blockReason, moral, remark, uname)
So(err, ShouldNotBeNil)
So(affect, ShouldBeGreaterThan, 0)
})
}
func TestReportLog(t *testing.T) {
var (
c = context.TODO()
dmid int64 = 2
)
Convey("test report log", t, func() {
lg, err := svr.ReportLog(c, dmid)
So(err, ShouldBeNil)
So(lg, ShouldNotBeEmpty)
})
}
func TestReportList(t *testing.T) {
var (
c = context.TODO()
page int64 = 1
size int64 = 100
start = "2017-05-10 00:00:00"
end = "2017-12-13 00:00:00"
order = "rp_time"
sort = "asc"
keyword = ""
tid = []int64{}
rpID = []int64{}
state = []int64{0, 1, 2, 3, 4, 5, 6, 7}
upOp = []int64{0, 1, 2}
rt = &model.Report{}
)
Convey("test report list", t, func() {
list, err := svr.ReportList(c, page, size, start, end, order, sort, keyword, tid, rpID, state, upOp, rt)
So(err, ShouldBeNil)
So(list, ShouldNotBeNil)
})
}
func TestDMReportJudge(t *testing.T) {
var (
err error
c = context.TODO()
cidDmids = map[int64][]int64{
9968618: {719923090}}
)
Convey("test report judge", t, func() {
err = svr.DMReportJudge(c, cidDmids, 122, "zhang1111")
So(err, ShouldBeNil)
})
}
func TestJudgeResult(t *testing.T) {
var (
c = context.TODO()
cid, dmid int64 = 10109084, 719213118
)
Convey("test judge result", t, func() {
err := svr.JudgeResult(c, cid, dmid, 1)
So(err, ShouldBeNil)
})
}

Some files were not shown because too many files have changed in this diff Show More