Create & Init Project...

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

View File

@@ -0,0 +1,24 @@
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/interface/main/dm2/cmd:all-srcs",
"//app/interface/main/dm2/conf:all-srcs",
"//app/interface/main/dm2/dao:all-srcs",
"//app/interface/main/dm2/http:all-srcs",
"//app/interface/main/dm2/lib/xregex:all-srcs",
"//app/interface/main/dm2/model:all-srcs",
"//app/interface/main/dm2/rpc/client:all-srcs",
"//app/interface/main/dm2/rpc/server:all-srcs",
"//app/interface/main/dm2/service:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,725 @@
### dm2的Gateway服务。
#### Version V3.3.17
> 1. 点赞接入grpc
#### Version V3.3.16
> 1. 字幕和蒙版迁移出view调用
> 2. 创作中心最近1000条弹幕30天强限制
#### Version V3.3.15
> 1. 创作中心最新1000条弹幕 limit 30d
#### Version V3.3.14
> 1. 创作中心最新1000条弹幕 接入搜索
#### Version V3.3.13
> 1. fix弹幕发送限速
#### Version V3.3.12
> 1. 弹幕发送黑名单
#### Version V3.3.11
> 1. use fanout
#### Version V3.3.10
> 1. 保护弹幕之前检查弹幕状态
#### Version V3.3.9
> 1. view aid allow empty
#### Version V3.3.8
> 1. account grpc
#### Version V3.3.7
> 1. 弹幕广播使用broadcast
#### Version V3.3.6
> 1. fix mysql count<0
#### Version V3.3.5
> 1. 去掉sync.pool
#### Version V3.3.4
> 1. 弹幕发送接入ai反垃圾限制
#### Version V3.3.3
> 1. localcache add subject
> 2. 分段弹幕大数据降级
#### Version V3.3.2
> 1. view 接口 localcache
#### Version V3.3.1
> 1. fix ipv4 collect
#### Version V3.3.0
> 1. 弹幕mobile view
> 2. 抽出appview的逻辑
> 3. bfs上传使用sdk
#### Version V3.2.3
> 1. 字幕提交 优化提示
> 2. 付费稿件up主可以发送弹幕
> 3. 弹幕协管操作次数限制,返回文案
#### Version V3.2.2
> 1. rebuild
#### Version V3.2.1
> 1. 字幕sql bug
#### Version V3.2.0
> 1. 弹幕广播添加限流
#### Version V3.1.25
> 1. 字幕添加开关
#### Version V3.1.24
> 1. remove addSlashes
#### Version V3.1.23
> 1. 添加开关配置
#### Version V3.1.22
> 1. 垃圾弹幕收集开关
#### Version V3.1.21
> 1. 弹幕发送接入行为日志
#### Version V3.1.20
> 1. spy service 降级
#### Version V3.1.19
> 1. figure ignore notfound error
#### Version V3.1.18
> 1. rpc error catch
#### Version V3.1.17
> 1. season id 换成grpc
#### Version V3.1.16
> 1. filter service 换成grpc
> 2. 弹幕发送添加垃圾弹幕屏蔽
#### Version V3.1.15
> 1. 移除web蒙版旧接口
#### Version V3.1.14
> 1. web蒙版扩展
#### Version V3.1.13
> 1. 弹幕点赞提示文案修改
#### Version V3.1.12
> 1. 增加弹幕发送时间限制
#### Version V3.1.11
> 1. location的Zone方法改为Info方法
#### Version V3.1.10
> 1. 字幕web端添加原文语言返回
#### Version V3.1.9
> 1. 去掉字幕灰度的接口
#### Version V3.1.8
> 1. 修改字幕举报description
#### Version V3.1.7
> 1. 字幕举报兼容没有信用分
#### Version V3.1.6
> 1. 字幕举报添加metadata
#### Version V3.1.5
> 1. 添加付费视频弹幕发送认证
#### Version V3.1.4
> 1. 新增弹幕时记录用户ip、port
#### Version V3.1.3
> 1. 添加字幕举报
#### Version V3.1.2
> 1. 分段弹幕不刷新redis
#### Version V3.1.1
> 1. 添加字幕字数限制
#### Version V3.1.0
> 1. 字幕语言新增删除状态
#### Version V3.0.8
> 1. 5.30下掉弹幕蒙版
#### Version V3.0.7
> 1. ajax接口xss
#### Version V3.0.6
> 1. 字幕验证时间戳+1s,兼容视频毫秒时长
#### Version V3.0.5
> 1. 字幕作者添加videoname返回
#### Version V3.0.4
> 1. 发弹幕去掉aidcid一致检测
#### Version V3.0.3
> 1. 添加敏感词检测
#### Version V3.0.2
> 1. 下掉移动端飘窗弹幕
#### Version V3.0.1
> 1. 弹幕发送校验aidcid关联
#### Version V3.0.0
> 1. 新增分段弹幕json接口
> 2. 新增历史弹幕json接口
> 3. 新增全段弹幕json接口
#### Version V2.10.16
> 1. http添加trace
#### Version V2.10.15
> 1. 聚合字幕mc
#### Version V2.10.14
> 1. 弹幕历史更换business
#### Version V2.10.13
> 1. 更新弹幕广告接口URI
#### Version V2.10.12
> 1. 字幕web和mobile分开
#### Version V2.10.11
> 1. 发送弹幕 ecode返回值校正
#### Version V2.10.10
> 1. rpc去掉语言验证
#### Version V2.10.9
> 1. 字幕缓存穿透bug
#### Version V2.10.8
> 1. 搜索空数据兼容
#### Version V2.10.7
> 1. view 接口添加singlegroup
#### Version V2.10.6
> 1. 增加字幕接口
#### Version V2.10.5
> 1. broadcast转义符导致错误 fix
#### Version V2.10.4
> 1. 弹幕点赞增加up主mid
#### Version V2.10.3
> 1. 蒙版缓存使用mc
> 2. use rpc.ServerConfig
#### Version V2.10.2
> 1. rebuild master
#### Version V2.10.1
> 1. 搜索索引更新接口对接sdk v3
#### Version V2.10.0
> 1. 新增弹幕广告
> 2. 分段弹幕缓存出错不再回源db
#### Version V2.9.13
> 1. 弹幕蒙版三期
#### Version V2.9.12
> 1. 优化历史弹幕日期索引查询
#### Version V2.9.11
> 1. remoteIP 更改
#### Version V2.9.10
> 1. 移除创作中心无用接口
#### Version V2.9.9
> 1. 内部接口新增recent和search
#### Version V2.9.8
> 1. identify迁移verify和auth
#### Version V2.9.7
> 1. 创作中心弹幕增加aid
#### Version V2.9.6
> 1. 修复高级弹幕购买状态bug
#### Version V2.9.5
> 1. 修复高级弹幕购买状态bug
#### Version V2.9.4
> 1. 修复创作中心弹幕搜索权限bug
#### Version V2.9.3
> 1. nil dm content
#### Version V2.9.2
> 1. 移动端弹幕蒙版
#### Version V2.9.1
> 1. fix verify
#### Version V2.9.0
> 1. 移除视频维度的屏蔽词
> 2. 增加up主针对高级弹幕申请的配置
> 3. 增加up主搜索弹幕列表使用es sdk v3
#### Version V2.8.10
> 1. 提高卡片弹幕灰度比例
#### Version V2.8.9
> 1. fix recent dm panic
#### Version V2.8.8
> 1. fix rows.Err() in rows.Scan
#### Version V2.8.7
> 1. 卡片弹幕实验策略变更
#### Version V2.8.6
> 1. 卡片弹幕改为从header里获取Buvid
#### Version V2.8.5
> 1. 移动端卡片弹幕配合天马分组实验
#### Version V2.8.4
> 1. 重新构建master
#### Version V2.8.3
> 1. 历史弹幕搜索使用v3接口
#### Version V2.8.2
> 1. 更新稿件分批获取方法
#### Version V2.8.1
> 1. update discovery appid
#### Version V2.8.0
> 1. 使用discovery rpc client
#### Version V2.7.11
> 1. 移动端ajax弹幕直接返回空
#### Version V2.7.10
> 1. archive duration缓存穿透
#### Version V2.7.9
> 1. redis fix hmget
#### Version V2.7.8
> 1. 缓存区分字幕弹幕和普通弹幕
#### Version V2.7.7
> 1. count的变更改为操作新库
#### Version V2.7.6
> 1. childpool的变更改为操作新库
#### Version V2.7.5
> 1. 重新构建master
#### Version V2.7.4
> 1. 移除ajax弹幕中的Mode7弹幕
> 2. 优化普罗米修斯的缓存上报
#### Version V2.7.3
> 1. 重新构建master
#### Version V2.7.2
> 1. 弹幕计数迁移到job
#### Version V2.7.1
> 1. 历史弹幕pagesize=5000
#### Version V2.7.0
> 1. update infoc sdk
#### V2.6.3
> 1. 弹幕subject缓存穿透
#### V2.6.2
> 1. 海外用户校验
#### V2.6.1
> 1. 弹幕蒙版相关接口添加
#### V2.6.0
> 1. 对接发号器
#### V2.5.12
> 1. 新增level1用户弹幕长度超过20提示
#### V2.5.11
> 1. 高级弹幕购买需要参数优化
> 2. 高级弹幕相关接口结构体优化
> 3. user filter列表RPC调用结构体优化
#### V2.5.10
> 1. 弹幕发送增加反垃圾过滤备注
#### V2.5.9
> 1. add csrf
#### V2.5.8
> 1. update bm engine
#### V2.5.7
> 1. 弹幕池变更为0时减小move_cnt
#### V2.5.6
> 1. 修复关闭分段弹幕时gzip bug
#### V2.5.5
> 1. up主拉黑用户接口增加限流
> 2. 历史弹幕接口及历史弹幕日期索引接口增加限流
#### V2.5.4
> 1. up主拉黑用户接口更新
#### V2.5.3
> 1. 重构历史弹幕
#### V2.5.2
> 1. up主屏蔽词添加接口兼容协管添加
#### V2.5.1
> 1. 修复关闭分段弹幕不生效的bug
#### V2.5.0
> 1. 迁移blademaster
#### V2.4.32
> 1. 移除屏蔽词sql中的排序
> 2. 过滤弹幕编辑中dmid=0的参数
#### V2.4.31
> 1. 修复dmid为空的操作日志
#### V2.4.30
> 1. 修复稿件mid变化导致的bug
#### V2.4.29
> 1. 变更弹幕池时更新move_count in dm_subject
#### V2.4.28
> 1. 使用弹幕主题中的mid做up主权限校验
#### V2.4.27
> 1. 添加高级弹幕返回存储bfs
#### V2.4.26
> 1. fix archiveinfos 批量100请求
#### V2.4.25
> 1. 新增弹幕属性变更rpc方法
> 2. 弹幕状态变更支持举报脚本删除
#### V2.4.24
> 1. dm_subject新增字段
#### V2.4.23
> 1. rank<=15000的用户设置字幕弹幕时增加条数限制
#### V2.4.22
> 1. 修复用户屏蔽词添加的bug
> 2. up主屏蔽词接口改为json参数
#### V2.4.21
> 1. 视频时长缓存使用memcached
#### V2.4.20
> 1. 用户添加屏蔽词接口改为批量新增接口
#### V2.4.19
> 1. 协管拉黑用户时日志记录弹幕内容
#### V2.4.18
> 1. 高级弹幕购买迁移dm -> dm2
#### V2.4.17
> 1. 迁移main目录
#### V2.4.16
> 1. up主屏蔽词对接新库
> 2. 重构屏蔽词服务
#### V2.4.15
> 1. 去掉oplogproc弹幕发送日志时间戳
#### V2.4.14
> 1. 修复OpLog弹幕发送日志时间戳
#### V2.4.13
> 1. 修复OpLog弹幕日志消费队列溢出
#### V2.4.12
> 1. 修复OpLog弹幕日志时间戳生成
#### V2.4.11
> 1. 修复弹幕风纪委bug
> 2. 弹幕实名制增加开关以及白名单
#### V2.4.10
> 1. 使用account-service v7
#### V2.4.9
> 1. 修复弹幕监控计数问题
#### V2.4.8
> 1. 移除剧透弹幕相关逻辑
#### V2.4.7
> 1. up主在自己的视频下发送顶端、底端弹幕不再受等级的限制
#### V2.4.6
> 1. 修复用户撤回判断弹幕逻辑
#### V2.4.5
> 1. 重构弹幕监控
#### V2.4.4
> 1. 添加发送屏蔽状态日志
#### V2.4.3
> 1. up主屏蔽词屏蔽类型 painc 修复
#### V2.4.2
> 1. up主屏蔽词屏蔽类型修改
#### V2.4.1
> 1. 分段弹幕开启实名制
#### V2.4.0
> 1. 添加业务操作infoc2日志
> 2. test 去除simplejson 依赖
#### V2.3.4
> 1. 修复特殊弹幕管理的bug
#### V2.3.3
> 1. 弹幕xml替换非法字符
#### V2.3.2
> 1. 新增弹幕状态变更rpc method
> 2. 新增弹幕池变更rpc method
#### V2.3.1
> 1. 新增用户端弹幕管理
> 2. 移除无用代码
#### V2.3.0
> 1. 新增弹幕计数rpc service
> 2. 提供弹幕发送、实名制开关状态给详情页
#### v2.2.23
> 1. localcache oid 请求大数据
#### v2.2.22
> 1. 修改弹幕池和弹幕状态平行权限的问题
#### v2.2.21
> 1. 修复cache.Save context
#### V2.2.20
> 1. 使用UserInfo替换Card
#### V2.2.19
> 1. 使用UserInfo替换MyInfo
#### V2.2.18
> 1. localcache oid不再请求大数据
#### V2.2.17
> 1. 弹幕发送计数迁移到dm2-job
#### V2.2.16
> 1. 调整弹幕发送时发送给kafka的key
> 2. 分段弹幕从缓存获取dmid时增加限制
#### V2.2.15
> 1. local cache dm subject and video duration
#### V2.2.14
> 1. 移除DmDmpost-T的双写
#### V2.2.13
> 1. 弹幕发送添加反垃圾功能
#### V2.2.12
> 1. 增加禁止发送弹幕功能
> 2. xml header中增加state字段
#### V2.2.11
> 1. 弹幕发送更新 dm_monitor 表
#### V2.2.10
> 1. 热加载local cache 配置
#### V2.2.9
> 1. 修复up正则匹配bug
#### V2.2.8
> 1. 添加弹幕和分段弹幕白名单,做本地缓存
> 2. 给大数据接口增加aid 参数
#### v2.2.7
> 1. 打开弹幕广播功能
#### V2.2.6
> 1. 修复数据库返回值导致的panic
#### V2.2.5
> 1. 修复DmDMpost-T双写
> 2. 关闭发送弹幕接口中的广播,待双写关闭时打开
#### V2.2.4
> 1. 弹幕发送双写 DmDmpost-T
#### V2.2.3
> 1. 迁移弹幕广播功能到弹幕发送接口
#### V2.2.2
> 1. 变更屏蔽词缓存key
#### V2.2.1
> 1. 修复高级弹幕购买缓存清理
#### V2.2.0
> 1. 新增弹幕发送接口
#### V2.1.18
> 1. 批量获取subjects状态筛选
#### V2.1.17
> 1. 去除弹幕镜像功能
#### V2.1.16
> 1. 风纪委弹幕列表sql优化2
#### V2.1.15
> 1. 风纪委弹幕列表sql优化
#### V2.1.14
> 1. subject 被关闭时仍返回弹幕列表
> 2. 更新prom 统计方法
#### V2.1.13
> 1. 注释单元测试(暂时)
#### V2.1.12
> 1. 点赞接口cid别名问题
#### V2.1.11
> 1. fix rec_switch flag
#### V2.1.10
> 1. 最新弹幕新老接口拆分
#### V2.1.9
> 1. 弹幕实名制
> 2. 更改实名白名单
#### V2.1.8
> 1. 弹幕点赞接口
#### V2.1.7
> 1. 移除childpool 3相应逻辑
#### V2.1.6
> 1. 修改最新弹幕返回aid
#### V2.1.5
> 1. 修改最新弹幕字段
#### V2.1.4
> 1. 更改弹幕列表v1回源逻辑
#### V2.1.3
> 1. 新增弹幕分布统计接口
#### V2.1.2
> 1. 新增弹幕弹幕镜像
> 2. 创作中心弹幕列表删除分P不存在bug
#### V2.1.1
> 1. 修复up删除弹幕不更新count
> 2. 同步老数据库dm_index 的 childpool 字段
#### V2.0.11
> 1. 修复缓存bug
#### V2.0.10
> 1. Page2 to Page3
> 2. Video2 to Video3
#### V2.0.9
> 1. 使用singleflight限制并发
#### V2.0.8
> 1. 新增up主最新1000条弹幕
#### V2.0.7
> 1. 新增一波单元测试
#### V2.0.6
> 1. 分段弹幕和非分段弹幕redis缓存分开
#### V2.0.5
> 1. 采用sync.pool优化GC
#### V2.0.4
> 1. 使用bytes.Buffer优化xml生成
#### V2.0.3
> 1. 新增弹幕风纪委功能
#### V2.0.2
> 1. 优化弹幕列表刷新逻辑
#### V2.0.1
> 1. 新增首页ajax弹幕列表接口
#### V2.0.0
> 1. 重构主站弹幕列表
#### V1.0.8
> 1. 依据dmid查询弹幕内容时并发查询
#### V1.0.7
> 1. 调用大数据接口时limit=2*maxlimit
> 2. 根据oid调用大数据多域名接口
#### V1.0.6
> 1. 调整弹幕显示数量为2*maxlimit
#### V1.0.5
> 1. 不再解析大数据json
> 2. 调整大数据接口降级逻辑
#### V1.0.4
> 1. 修复 .so后缀使用时res["code"]问题
#### V1.0.3
> 1. 合并到大仓库
#### V1.0.2
> 1. 添加大数据降级日志
#### V1.0.1
> 1. 修复弹幕上限分页逻辑
#### V1.0.0
> 1. 族群弹幕初始版本

View File

@@ -0,0 +1,11 @@
# Owner
liangkai
renwei
# Author
liangkai
renwei
# Reviewer
liangkai
renwei

View File

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

View File

@@ -0,0 +1,4 @@
### dm2的api服务
##### 项目说明
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 = ["dm2-test.toml"],
importpath = "go-common/app/interface/main/dm2/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/dm2/conf:go_default_library",
"//app/interface/main/dm2/http:go_default_library",
"//app/interface/main/dm2/rpc/server:go_default_library",
"//app/interface/main/dm2/service:go_default_library",
"//library/ecode/tip:go_default_library",
"//library/log:go_default_library",
"//library/net/trace:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,310 @@
# This is a TOML document. Boom.
[infoc2]
taskID = "000279"
proto = "tcp"
addr = "172.18.33.125:15140"
chanSize = 10240
[db]
[db.dmwriter]
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.dmwriter.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[db.dmreader]
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.dmreader.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[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 = "200ms"
execTimeout = "200ms"
tranTimeout = "200ms"
[db.dm.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[redis]
[redis.dm]
name = "dm2"
proto = "tcp"
addr = "172.18.33.60:6890"
active = 10
idle = 5
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "24h"
[redis.dmSeg]
name = "dm2"
proto = "tcp"
addr = "172.18.33.60:6890"
active = 10
idle = 5
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "24h"
[redis.dmRct]
name = "dm2"
proto = "tcp"
addr = "172.18.33.60:6890"
active = 10
idle = 5
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "720h"
[memcache]
[memcache.dm]
name = "dm2"
proto = "tcp"
addr = "127.0.0.1:11211"
idle = 5
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
dmExpire = "24h"
subjectExpire = "24h"
ajaxExpire = "1h"
[memcache.filter]
name = "filter"
proto = "tcp"
addr = "172.16.33.54:11211"
idle = 5
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
expire = "1h"
[memcache.subtitle]
name = "subtitle"
proto = "tcp"
addr = "127.0.0.1:11211"
idle = 5
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
expire = "3m"
[localcache]
oids = [1221,1223]
expire = "60s"
[httpServer]
addr = "0.0.0.0:6701"
maxListen = 1000
timeout = "1s"
[rpcServer]
discoverOff = false
token = "123456"
[[rpcServer.servers]]
proto = "tcp"
addr = "0.0.0.0:6709"
weight = 10
group = "test"
[rpcServer.zookeeper]
root = "/microservice/dm2/"
addrs = ["172.18.33.172:2181"]
timeout = "30s"
[host]
ai = "http://172.16.0.26:8281"
api = "http://uat-api.bilibili.co"
archive = "http://archive.api.bilibili.co"
message = "http://message.bilibili.co"
search = "http://uat-bili-search.bilibili.co"
advert = "http://172.16.38.67:8185"
maskCloud = "http://172.18.33.138:2281/testbucket/"
[httpCli]
key = "f6433799dbd88751"
secret = "36f8ddb1806207fe07013ab6a77a3935"
dial = "1s"
timeout = "1s"
keepAlive = "60s"
timer = 1000
[httpCli.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[archiveRPC]
group = "test"
timeout = "3s"
[accountRPC]
group = "groupapp"
timeout = "1s"
[assistRPC]
group="test"
timeout = "1s"
[coinRPC]
timeout = "1s"
[seqRPC]
policy = "sharding"
timeout = "1s"
[seq]
[seq.dm]
businessID = 10
token = "Nf9phmDdzjTMW9M5V8YQuLpVTwhvn5IO"
[seq.subtitle]
businessID = 11
token = "Nf9phmDdzjTMW9M5V8YQuLpVTwhvn5IO"
[locationRPC]
timeout = "2s"
[relationRPC]
timeout = "1s"
[thumbupRPC]
timeout = "100ms"
[supervision]
completed = false
startTime = "2018-05-02 22:15:00"
endTime = "2019-05-05 08:00:00"
location = "中国"
[elastic]
host = "http://uat-manager.bilibili.co"
[elastic.httpClient]
key = "f6433799dbd88751"
secret = "36f8ddb1806207fe07013ab6a77a3935"
dial = "1s"
timeout = "1s"
keepAlive = "60s"
timer = 1000
[elastic.httpClient.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[databus]
key = "0Pub71UFEMKXu63qtztt"
secret= "0Pub71UFEMKXu63qtztu"
group= "DMJob-UGC-P"
topic= "DMJob-T"
action="pub"
name = "dm2"
proto = "tcp"
addr = "172.16.33.158:6205"
active = 5
idle = 1
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
[actionpub]
key = "0Pub71WwEMKXu63qtztu"
secret= "0Pub71WwEMKXu63qtztv"
group= "DMAction-UGC-P"
topic= "DMAction-T"
action="pub"
name = "dm2"
proto = "tcp"
addr = "172.16.33.158:6205"
active = 5
idle = 1
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
[subtitleCheckPub]
key = "170e302355453683"
secret= "51b66df3ebeca2b08f0017f350b6f0ce"
group= "SubtitleCheck-MainCommunity-P"
topic= "SubtitleCheck-T"
action="pub"
name = "dm2"
proto = "tcp"
addr = "172.16.38.154:6205"
active = 5
idle = 1
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
[realname]
switchOn = false
whitelist = [10109417,1221]
[realname.threshold]
"1,2" = 1010
[antispam]
on=true
second=5
n=10
hour=1
m=5
[antispam.redis]
name = "dm2/antispam"
proto = "tcp"
addr = "172.18.33.60:6890"
active = 10
idle = 5
dialTimeout = "500ms"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
expire = "10m"
[bfs]
host = "http://uat-bfs.bilibili.co"
timeout = "5s"
bucket = "test"
key = "221bce6492eba70f"
secret = "6eb80603e85842542f9736eb13b7e3"

View File

@@ -0,0 +1,53 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"time"
"go-common/app/interface/main/dm2/conf"
"go-common/app/interface/main/dm2/http"
rpc "go-common/app/interface/main/dm2/rpc/server"
"go-common/app/interface/main/dm2/service"
ecode "go-common/library/ecode/tip"
"go-common/library/log"
"go-common/library/net/trace"
)
func main() {
flag.Parse()
if err := conf.Init(); err != nil {
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 log.Close()
// service init
svc := service.New(conf.Conf)
http.Init(conf.Conf, svc)
ecode.Init(conf.Conf.Ecode)
rpcSvc := rpc.New(conf.Conf, svc)
// init signal
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("dm2 get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
rpcSvc.Close()
time.Sleep(1 * time.Second)
log.Info("dm2 interface exit")
return
case syscall.SIGHUP:
// TODO reload
default:
return
}
}
}

View File

@@ -0,0 +1,49 @@
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/interface/main/dm2/conf",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/cache/memcache:go_default_library",
"//library/cache/redis:go_default_library",
"//library/conf:go_default_library",
"//library/database/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/antispam:go_default_library",
"//library/net/http/blademaster/middleware/auth: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",
"//library/time: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,284 @@
package conf
import (
"errors"
"flag"
"go-common/library/cache/memcache"
"go-common/library/cache/redis"
"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/antispam"
"go-common/library/net/http/blademaster/middleware/auth"
"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"
"go-common/library/time"
"github.com/BurntSushi/toml"
)
var (
confPath string
client *conf.Client
// Conf config export var
Conf = &Config{}
)
// Config dm config struct
type Config struct {
// ecode
Ecode *ecode.Config
// log
Xlog *log.Config
Infoc2 *infoc.Config
// tracer
Tracer *trace.Config
Auth *auth.Config
Verify *verify.Config
// database
DB *DB
// redis
Redis *Redis
// memcache
Memcache *Memcache
// localcache
Localcache *Localcache
// host
Host *Host
// http
HTTPServer *bm.ServerConfig
// http client
HTTPCli *bm.ClientConfig
// rpc client
ArchiveRPC *rpc.ClientConfig
// account rpc client
AccountRPC *warden.ClientConfig
// assist rpc client
AssistRPC *rpc.ClientConfig
//coin rpc client
CoinRPC *rpc.ClientConfig
// thumbup rpc client
ThumbupRPC *warden.ClientConfig
// relation rpc client
RelationRPC *rpc.ClientConfig
// seq-server rpc client
SeqRPC *rpc.ClientConfig
Seq *Seq
// Location rpc client
LocationRPC *rpc.ClientConfig
// MemberRpc Rpc
MemberRPC *rpc.ClientConfig
// Filter Rpc
FilterRPC *warden.ClientConfig
// Figure RPC
FigureRPC *rpc.ClientConfig
// UgcPayRPC RPC
UgcPayRPC *warden.ClientConfig
// SpyRPC RPC
SpyRPC *rpc.ClientConfig
// Season RPC
SeasonRPC *warden.ClientConfig
// databus
Databus *databus.Config
ActionPub *databus.Config
// dm list realname
Realname *Realname
// dm rpc server
RPCServer *rpc.ServerConfig
// Antispam
Antispam *antispam.Config
// supervision conf
Supervision *Supervision
// Elastic config
Elastic *elastic.Config
// Bfs
Bfs *Bfs
// Subtitle Check Databus
SubtitleCheckPub *databus.Config
// Garbage danmu Switch
Switch *Switch
// BroadcastLimit
BroadcastLimit *BroadcastLimit
// DmFlag
DmFlag *DmFlag
}
// DmFlag .
type DmFlag struct {
RecFlag int
RecText string
RecSwitch int
}
// BroadcastLimit broadcast limit
type BroadcastLimit struct {
Limit int
Interval int
}
// Switch .
type Switch struct {
GarbageDanmu bool
}
// Bfs .
type Bfs struct {
Client *bfs.Config
BucketSubtitle string
}
//Seq Conf
type Seq struct {
DM *struct {
BusinessID int64
Token string
}
Subtitle *struct {
BusinessID int64
Token string
}
}
// DB mysql
type DB struct {
DMReader *sql.Config
DMWriter *sql.Config
DM *sql.Config
}
// Redis dm redis
type Redis struct {
DM *struct {
*redis.Config
Expire time.Duration
}
DMRct *struct {
*redis.Config
Expire time.Duration
}
DMSeg *struct {
*redis.Config
Expire time.Duration
}
}
// Memcache dm memcache
type Memcache struct {
DM *struct {
*memcache.Config
DMExpire time.Duration
SubjectExpire time.Duration
HistoryExpire time.Duration
AjaxExpire time.Duration
DMMaskExpire time.Duration
}
Filter *struct {
*memcache.Config
Expire time.Duration
}
Subtitle *struct {
*memcache.Config
Expire time.Duration
}
DMSeg *struct {
*memcache.Config
DMExpire time.Duration
DMLimiterExpire time.Duration
}
}
// Localcache cache stored in local
type Localcache struct {
Oids []int64
Expire time.Duration
ViewAids []int64
ViewExpire time.Duration
}
// Realname realname switch and config
type Realname struct {
SwitchOn bool
Whitelist []int64
Threshold map[string]int64
}
// Host http host
type Host struct {
AI string
API string
Archive string
Message string
Search string
MaskCloud string
Advert string
Upos string
Self string
}
// Supervision supervision .
type Supervision struct {
Completed bool
StartTime string
EndTime string
Location 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
}

View File

@@ -0,0 +1,118 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"advert_test.go",
"archive_test.go",
"bfs_test.go",
"bigdata_test.go",
"broadcast_test.go",
"dao_test.go",
"databus_test.go",
"mask_test.go",
"mc_filter_test.go",
"mc_limiter_test.go",
"mc_seg_test.go",
"mc_subtitle_test.go",
"mc_test.go",
"mc_wave_form_test.go",
"mysql_advance_test.go",
"mysql_filter_test.go",
"mysql_subtitle_test.go",
"mysql_test.go",
"notify_test.go",
"redis_rct_test.go",
"redis_seg_test.go",
"redis_test.go",
"search_test.go",
"upos_test.go",
"user_log_test.go",
"workflow_test.go",
],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/interface/main/dm2/conf:go_default_library",
"//app/interface/main/dm2/model:go_default_library",
"//library/log:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"advert.go",
"archive.go",
"bfs.go",
"bigdata.go",
"broadcast.go",
"dao.go",
"databus.go",
"mask.go",
"mc.go",
"mc_filter.go",
"mc_limiter.go",
"mc_seg.go",
"mc_subtitle.go",
"mc_wave_form.go",
"mysql.go",
"mysql_advance.go",
"mysql_filter.go",
"mysql_subtitle.go",
"notify.go",
"redis.go",
"redis_rct.go",
"redis_seg.go",
"search.go",
"upos.go",
"user_log.go",
"workflow.go",
],
importpath = "go-common/app/interface/main/dm2/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/dm2/conf:go_default_library",
"//app/interface/main/dm2/model:go_default_library",
"//app/interface/main/videoup/model/archive:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/cache/redis: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/queue/databus/report:go_default_library",
"//library/stat/prom:go_default_library",
"//library/sync/errgroup:go_default_library",
"//library/time:go_default_library",
"//library/xstr: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,53 @@
package dao
import (
"context"
"fmt"
"net/url"
"go-common/app/interface/main/dm2/model"
"go-common/library/ecode"
"go-common/library/net/metadata"
"github.com/pkg/errors"
)
const (
_adURL = "/bce/api/bce/wise"
)
func (d *Dao) adURI() string {
return d.conf.Host.Advert + _adURL
}
// DMAdvert dm advert.
func (d *Dao) DMAdvert(c context.Context, aid, cid, mid, build int64, buvid, mobiApp, adExtra string) (data *model.AD, err error) {
var (
res *struct {
Code int `json:"code"`
Data *model.AD `json:"data"`
}
)
ip := metadata.String(c, metadata.RemoteIP)
params := url.Values{}
params.Set("aid", fmt.Sprint(aid))
params.Set("cid", fmt.Sprint(cid))
params.Set("buvid", buvid)
params.Set("resource", model.Resource(mobiApp))
params.Set("mobi_app", mobiApp)
params.Set("build", fmt.Sprint(build))
params.Set("ip", ip)
params.Set("ad_extra", adExtra)
if mid != 0 {
params.Set("mid", fmt.Sprint(mid))
}
if err = d.httpCli.Get(c, d.adURI(), ip, params, &res); err != nil {
return
}
if res.Code != ecode.OK.Code() {
err = errors.Wrap(ecode.Int(res.Code), d.adURI()+"?"+params.Encode())
return
}
data = res.Data
return
}

View File

@@ -0,0 +1,24 @@
package dao
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestDMAdvert(t *testing.T) {
Convey("dm advert", t, func() {
var (
c = context.TODO()
aid int64 = 10100572
cid int64 = 10115256
mid int64 = 12345881
build int64 = 8111
adExtra = ""
buvid = "5400000"
mobiApp = "android"
)
testDao.DMAdvert(c, aid, cid, mid, build, buvid, mobiApp, adExtra)
})
}

View File

@@ -0,0 +1,43 @@
package dao
import (
"context"
"fmt"
"go-common/app/interface/main/videoup/model/archive"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_typesURL = "/videoup/types"
)
func (d *Dao) typesURI() string {
return d.conf.Host.Archive + _typesURL
}
// TypeMapping is second types opposite first types.
func (d *Dao) TypeMapping(c context.Context) (rmap map[int16]int16, err error) {
var res struct {
Code int `json:"code"`
Message string `json:"message"`
Data map[int16]*archive.Type `json:"data"`
}
if err = d.httpCli.Get(c, d.typesURI(), "", nil, &res); err != nil {
log.Error("d.httpCli.Get() error(%v) typesURI(%s)", err, d.typesURI())
return
}
if res.Code != ecode.OK.Code() {
err = fmt.Errorf("bangumi seasons api failed(%d)", res.Code)
log.Error("url(%s) res code(%d)", d.typesURI(), res.Code)
return
}
rmap = make(map[int16]int16, len(res.Data))
for _, v := range res.Data {
if v.PID != 0 {
rmap[v.ID] = v.PID
}
}
return
}

View File

@@ -0,0 +1,34 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaotypesURI(t *testing.T) {
convey.Convey("typesURI", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := testDao.typesURI()
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoTypeMapping(t *testing.T) {
convey.Convey("TypeMapping", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rmap, err := testDao.TypeMapping(c)
ctx.Convey("Then err should be nil.rmap should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rmap, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,22 @@
package dao
import (
"context"
"go-common/library/database/bfs"
"go-common/library/log"
)
// UploadBfs .
func (d *Dao) UploadBfs(c context.Context, fileName string, bs []byte) (location string, err error) {
if location, err = d.bfsCli.Upload(c, &bfs.Request{
Bucket: d.conf.Bfs.BucketSubtitle,
Filename: fileName,
ContentType: "application/json",
File: bs,
}); err != nil {
log.Error("bfs.BfsDmUpload error(%v)", err)
return
}
return
}

View File

@@ -0,0 +1,21 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoUploadBfs(t *testing.T) {
convey.Convey("UploadBfs", t, func(ctx convey.C) {
var (
c = context.Background()
fileName = ""
bs = []byte("123")
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.UploadBfs(c, fileName, bs)
})
})
}

View File

@@ -0,0 +1,53 @@
package dao
import (
"context"
"encoding/json"
"fmt"
"net/url"
"strconv"
"go-common/library/log"
"go-common/library/net/metadata"
)
const (
_uri = "/danmaku/%d/rec"
)
func (d *Dao) danmakuURI(oid int64) string {
return d.conf.Host.AI + fmt.Sprintf(_uri, oid%4)
}
// RecFlag get recommend flags from bigdata.
func (d *Dao) RecFlag(c context.Context, mid, aid, oid, limit, ps, pe int64, plat int32) (data []byte, err error) {
var res struct {
Code int64 `json:"code"`
Msg string `json:"message"`
Data json.RawMessage `json:"data"`
}
uri := d.danmakuURI(oid)
params := url.Values{}
realIP := metadata.String(c, metadata.RemoteIP)
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("aid", strconv.FormatInt(aid, 10))
params.Set("oid", strconv.FormatInt(oid, 10))
params.Set("limit", strconv.FormatInt(limit, 10))
params.Set("ps", strconv.FormatInt(ps, 10))
params.Set("pe", strconv.FormatInt(pe, 10))
params.Set("plat", strconv.FormatInt(int64(plat), 10))
params.Set("ip", realIP)
if err = d.httpCli.Get(c, uri, realIP, params, &res); err != nil {
PromError(uri)
log.Error("d.httpCli.Get(%s?%s) error(%v)", uri, params.Encode(), err)
return
}
if res.Code != 0 {
PromError(uri)
log.Error("d.httpCli.Get(%s?%s) code:%d msg:%s", uri, params.Encode(), res.Code, res.Msg)
err = fmt.Errorf("bigdata response code(%d) error", res.Code)
return
}
data = res.Data
return
}

View File

@@ -0,0 +1,40 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaodanmakuURI(t *testing.T) {
convey.Convey("danmakuURI", t, func(ctx convey.C) {
var (
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := testDao.danmakuURI(oid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoRecFlag(t *testing.T) {
convey.Convey("RecFlag", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
aid = int64(0)
oid = int64(0)
limit = int64(0)
ps = int64(0)
pe = int64(0)
plat = int32(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.RecFlag(c, mid, aid, oid, limit, ps, pe, plat)
})
})
}

View File

@@ -0,0 +1,85 @@
package dao
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
"net/url"
"go-common/library/log"
"go-common/library/net/metadata"
)
const (
_goimChatURI = "/x/internal/chat/push/room"
_broadcastURI = "/x/internal/broadcast/push/room"
_broadcastDmOperation = 1000
_broadcastDmRoomFmt = "video://%d/%d" //video://{aid}/{cid}
)
func (d *Dao) goimChatURI() string {
return d.conf.Host.API + _goimChatURI
}
func (d *Dao) broadcastURI() string {
return d.conf.Host.API + _broadcastURI
}
// BroadcastInGoim send dm msg in realtime.
func (d *Dao) BroadcastInGoim(c context.Context, cid, aid int64, info json.RawMessage) (err error) {
var (
res struct {
Code int64 `json:"code"`
}
data = map[string]interface{}{
"cmd": "DM",
"info": info,
}
)
v, err := json.Marshal(data)
if err != nil {
log.Error("json.Marshal(%s) error(%v)", info, err)
return
}
url := fmt.Sprintf("%s?cids=%d&aid=%d", d.goimChatURI(), cid, aid)
req, err := http.NewRequest("POST", url, bytes.NewReader(v))
if err != nil {
log.Error("broadcast http.NewRequest() error(%v)", err)
return
}
if err = d.httpCli.Do(c, req, &res); err != nil {
log.Error("httpCli.Do(%s) error(%v)", url, err)
return
}
if res.Code != 0 {
err = fmt.Errorf("broadcast api failed(%d)", res.Code)
log.Error("broadcast(%s) res code(%d)", url, res.Code)
}
return
}
// Broadcast send dm msg in realtime.
func (d *Dao) Broadcast(c context.Context, cid, aid int64, msg string) (err error) {
var (
res struct {
Code int64 `json:"code"`
}
)
params := url.Values{}
params.Set("operation", fmt.Sprint(_broadcastDmOperation))
params.Set("room", fmt.Sprintf(_broadcastDmRoomFmt, aid, cid))
params.Set("message", msg)
if err = d.httpCli.Post(c, d.broadcastURI(), metadata.String(c, metadata.RemoteIP), params, &res); err != nil {
log.Error("httpCli.Do(%s) error(%v)", d.broadcastURI(), err)
return
}
if res.Code != 0 {
err = fmt.Errorf("broadcast api failed(%d)", res.Code)
log.Error("broadcast(%s) res code(%d)", d.broadcastURI(), res.Code)
}
return
}

View File

@@ -0,0 +1,19 @@
package dao
import (
"fmt"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestBroadcast(t *testing.T) {
Convey("err should be nil", t, func() {
var err error
info := []byte(fmt.Sprintf(`["%.2f,%d,%d,%d,%d,%d,%d,%s,%d","%s"]`, 1.01, 0, 25, 0xFF, 1123, 23, 0, "abc", 1, `德玛西亚万岁\\(≧▽≦)/`))
if err = testDao.BroadcastInGoim(c, 123, 456, info); err != nil {
t.Logf("testDao.Broadcast(%s) error(%v)", info, err)
}
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,195 @@
package dao
import (
"context"
"time"
"go-common/app/interface/main/dm2/conf"
"go-common/library/cache/memcache"
"go-common/library/cache/redis"
"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"
"go-common/library/stat/prom"
)
var (
errorsCount = prom.BusinessErrCount
missedCount = prom.CacheMiss
cachedCount = prom.CacheHit
)
// Dao dm dao.
type Dao struct {
conf *conf.Config
// mysql
dmWriter *sql.DB
dmReader *sql.DB
dbDM *sql.DB
// redis
dmRds *redis.Pool
dmRdsExpire int32
// recent dm redis
dmRctRds *redis.Pool
dmRctExpire int32
// segment dm redis
dmSegRds *redis.Pool
dmSegExpire int32
// memcache
dmMC *memcache.Pool
dmExpire int32
subjectExpire int32
historyExpire int32
ajaxExpire int32
dmMaskExpire int32
filterMC *memcache.Pool
filterMCExpire int32
dmSegMC *memcache.Pool
dmSegMCExpire int32
dmLimiterMCExpire int32
// http
httpCli *bm.Client
// databus
databus *databus.Databus
actionPub *databus.Databus
// elastic
elastic *elastic.Elastic
// bfsCli
bfsCli *bfs.BFS
// subtitle mc
subtitleMc *memcache.Pool
subtitleMcExpire int32
subtitleCheckPub *databus.Databus
}
// New new a dao and return.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
conf: c,
// mysql
dmWriter: sql.NewMySQL(c.DB.DMWriter),
dmReader: sql.NewMySQL(c.DB.DMReader),
dbDM: sql.NewMySQL(c.DB.DM),
// redis
dmRds: redis.NewPool(c.Redis.DM.Config),
dmRdsExpire: int32(time.Duration(c.Redis.DM.Expire) / time.Second),
// recent dm redis
dmRctRds: redis.NewPool(c.Redis.DMRct.Config),
dmRctExpire: int32(time.Duration(c.Redis.DMRct.Expire) / time.Second),
// segment dm redis
dmSegRds: redis.NewPool(c.Redis.DMSeg.Config),
dmSegExpire: int32(time.Duration(c.Redis.DMSeg.Expire) / time.Second),
// memcache
dmMC: memcache.NewPool(c.Memcache.DM.Config),
dmExpire: int32(time.Duration(c.Memcache.DM.DMExpire) / time.Second),
subjectExpire: int32(time.Duration(c.Memcache.DM.SubjectExpire) / time.Second),
historyExpire: int32(time.Duration(c.Memcache.DM.HistoryExpire) / time.Second),
ajaxExpire: int32(time.Duration(c.Memcache.DM.AjaxExpire) / time.Second),
dmMaskExpire: int32(time.Duration(c.Memcache.DM.DMMaskExpire) / time.Second),
filterMC: memcache.NewPool(c.Memcache.Filter.Config),
filterMCExpire: int32(time.Duration(c.Memcache.Filter.Expire) / time.Second),
dmSegMC: memcache.NewPool(c.Memcache.DMSeg.Config),
dmSegMCExpire: int32(time.Duration(c.Memcache.DMSeg.DMExpire) / time.Second),
dmLimiterMCExpire: int32(time.Duration(c.Memcache.DMSeg.DMLimiterExpire) / time.Second),
// http
httpCli: bm.NewClient(c.HTTPCli),
// databus
databus: databus.New(c.Databus),
actionPub: databus.New(c.ActionPub),
// elastic
elastic: elastic.NewElastic(c.Elastic),
// bfscli
bfsCli: bfs.New(c.Bfs.Client),
// subtitle MC
subtitleMc: memcache.NewPool(c.Memcache.Subtitle.Config),
subtitleMcExpire: int32(time.Duration(c.Memcache.Subtitle.Expire) / time.Second),
subtitleCheckPub: databus.New(c.SubtitleCheckPub),
}
return
}
func (d *Dao) hitSubject(oid int64) int64 {
return oid % _subjectSharding
}
func (d *Dao) hitIndex(oid int64) int64 {
return oid % _indexSharding
}
func (d *Dao) hitContent(dmid int64) int64 {
return dmid % _contentSharding
}
// BeginBiliDMTrans begin db transaction.
func (d *Dao) BeginBiliDMTrans(c context.Context) (*sql.Tx, error) {
return d.dbDM.Begin(c)
}
// Ping ping success.
func (d *Dao) Ping(c context.Context) (err error) {
if err = d.dmReader.Ping(c); err != nil {
log.Error("d.dmReader error(%v)", err)
return
}
if err = d.dmWriter.Ping(c); err != nil {
log.Error("d.dmWriter error(%v)", err)
return
}
// mc
dmMC := d.dmMC.Get(c)
defer dmMC.Close()
if err = dmMC.Set(&memcache.Item{Key: "ping", Value: []byte("pong"), Expiration: 0}); err != nil {
log.Error("dmMC.Set error(%v)", err)
return
}
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
}
dmSegMC := d.dmSegMC.Get(c)
defer dmSegMC.Close()
if err = dmSegMC.Set(&memcache.Item{Key: "ping", Value: []byte("pong"), Expiration: 0}); err != nil {
log.Error("dmSegMC.Set error(%v)", err)
return
}
// dm redis
dmConn := d.dmRds.Get(c)
defer dmConn.Close()
if _, err = dmConn.Do("SET", "ping", "pong"); err != nil {
log.Error("dmConn.Do(SET) error(%v)", err)
return
}
rctRdsConn := d.dmRctRds.Get(c)
defer rctRdsConn.Close()
if _, err = rctRdsConn.Do("SET", "ping", "pong"); err != nil {
log.Error("rctRdsConn.Do(SET) error(%v)", err)
return
}
// segment dm redis
segRdsConn := d.dmSegRds.Get(c)
defer segRdsConn.Close()
if _, err = segRdsConn.Do("SET", "ping", "pong"); err != nil {
log.Error("segRdsConn.Do(SET) error(%v)", err)
}
return
}
// PromError prom error
func PromError(name string) {
errorsCount.Incr(name)
}
// PromCacheHit prom cache hit
func PromCacheHit(name string, v int64) {
cachedCount.Add(name, v)
}
// PromCacheMiss prom cache hit
func PromCacheMiss(name string, v int64) {
missedCount.Add(name, v)
}

View File

@@ -0,0 +1,36 @@
package dao
import (
"context"
"flag"
"os"
"testing"
"go-common/app/interface/main/dm2/conf"
"go-common/library/log"
)
var (
testDao *Dao
c = context.TODO()
)
func TestMain(m *testing.M) {
flag.Set("app_id", "main.community.dm2")
flag.Set("conf_token", "41bebe87fc9df75601583db2672f7c34")
flag.Set("tree_id", "2291")
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,55 @@
package dao
import (
"context"
"encoding/json"
"strconv"
"go-common/app/interface/main/dm2/model"
"go-common/library/log"
)
// PubDatabus pub cache update message to databus.
func (d *Dao) PubDatabus(c context.Context, tp int32, pid, oid, cnt, n, duration int64) (err error) {
var (
jobParams = &model.JobParam{
Type: tp,
Oid: oid,
Pid: pid,
Cnt: cnt,
Num: n,
Duration: duration,
}
)
value, err := json.Marshal(jobParams)
if err != nil {
log.Error("json.Marshal(%v) error(%v)", jobParams, err)
return
}
msg := model.Action{Action: model.ActionIdx, Data: value}
if err = d.databus.Send(c, strconv.FormatInt(oid, 10), msg); err != nil {
log.Error("databus.Send(%v) error(%v)", msg, err)
}
return
}
// SendAction send action to job.
func (d *Dao) SendAction(c context.Context, k string, act *model.Action) (err error) {
if err = d.actionPub.Send(c, k, act); err != nil {
log.Error("actionPub.Send(action:%s,data:%s) error(%v)", act.Action, act.Data, err)
} else {
log.Info("actionPub.Send(action:%s,data:%s) success", act.Action, act.Data)
}
return
}
// SendSubtitleCheck .
func (d *Dao) SendSubtitleCheck(c context.Context, key string, msg *model.SubtitleCheckMsg) (err error) {
if err = d.subtitleCheckPub.Send(c, key, msg); err != nil {
log.Error("actionPub.Send(key:%s,msg:%+v) error(%v)", key, msg, err)
} else {
log.Error("actionPub.Send(key:%s,msg:%+v) success", key, msg)
}
return
}

View File

@@ -0,0 +1,42 @@
package dao
import (
"context"
"encoding/json"
"fmt"
"testing"
"go-common/app/interface/main/dm2/model"
. "github.com/smartystreets/goconvey/convey"
)
func TestPubDatabus(t *testing.T) {
var (
tp int32 = 1
aid int64 = 10097265
oid int64 = 1508
cnt int64 = 26
num int64 = 1
duration int64 = 9031000
c = context.TODO()
)
Convey("flush segment dm xml", t, func() {
err := testDao.PubDatabus(c, tp, aid, oid, cnt, num, duration)
So(err, ShouldBeNil)
})
}
func TestSendAction(t *testing.T) {
var (
c = context.TODO()
flush = &model.Flush{Oid: 1221, Type: 1}
)
Convey("flush xml", t, func() {
data, err := json.Marshal(flush)
So(err, ShouldBeNil)
act := &model.Action{Action: model.ActionFlush, Data: data}
err = testDao.SendAction(c, fmt.Sprint(flush.Oid), act)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,44 @@
package dao
import (
"context"
"go-common/app/interface/main/dm2/model"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
_updateMask = "REPLACE INTO dm_masking(cid,plat,fps,time,list) VALUES (?,?,?,?,?)"
_selectMask = "SELECT cid,plat,fps,time,list FROM dm_masking WHERE cid=? AND plat=?"
)
// UpdateMask replace dm_masking table for web
func (d *Dao) UpdateMask(c context.Context, cid, maskTime int64, fps int32, plat int8, list string) (err error) {
if _, err = d.dbDM.Exec(c, _updateMask, cid, plat, fps, maskTime, list); err != nil {
log.Error("biliDM.Exec(%v, %v %v %v %v %v) error(%v)", _updateMask, cid, plat, fps, maskTime, list, err)
}
return
}
// MaskList get mask linfo
func (d *Dao) MaskList(c context.Context, cid int64, plat int8) (m *model.Mask, err error) {
m = &model.Mask{}
var tmp string
row := d.dbDM.QueryRow(c, _selectMask, cid, plat)
if err = row.Scan(&m.Cid, &m.Plat, &m.FPS, &m.Time, &tmp); err != nil {
if err == sql.ErrNoRows {
m = nil
err = nil
} else {
log.Error("MaskList.rows.Scan(cid:%d plat:%d) error(%v)", cid, plat, err)
}
return
}
if tmp == "" {
m = nil
return
}
m.MaskURL = d.conf.Host.MaskCloud + tmp
return
}

View File

@@ -0,0 +1,37 @@
package dao
import (
"context"
"testing"
"go-common/app/interface/main/dm2/model"
. "github.com/smartystreets/goconvey/convey"
)
func TestUpdateMask(t *testing.T) {
var (
c = context.TODO()
cid int64 = 2386051
maskTime int64 = 60
fps int32 = 25
list = "26777486_s0_0_1499,26777486_s1_1500_2999,26777486_s2_3000_4499,26777486_s3_4500_5999,26777486_s4_6000_7499,26777486_s5_7500_7897"
)
Convey("test update mask", t, func() {
err := testDao.UpdateMask(c, cid, maskTime, fps, model.MaskPlatMbl, list)
So(err, ShouldBeNil)
})
}
func TestMaskList(t *testing.T) {
var (
c = context.TODO()
cid int64 = 1352
)
Convey("test mobile mask list", t, func() {
res, err := testDao.MaskList(c, cid, model.MaskPlatMbl)
t.Logf("==============%+v", res)
So(err, ShouldBeNil)
So(res, ShouldNotBeEmpty)
})
}

View File

@@ -0,0 +1,642 @@
package dao
import (
"context"
"fmt"
"hash/crc32"
"strconv"
"go-common/app/interface/main/dm2/model"
"go-common/library/cache/memcache"
"go-common/library/log"
)
var (
_lockvalue = []byte("1")
)
const (
_prefixPubLock = "dm_pub_"
_prefixCharPubLock = "dm_pub_char_"
_prefixXML = "dm_xml_"
_prefixSub = "s_"
_prefixAjax = "dm_ajax_"
_prefixDMJudge = "dm_judge_%d_%d_%d"
_prefixDMLimit = "dm_limit_"
_prefixAdvanceCmt = "cache:AdvanceComment:%d@%d.%s"
_prefixAdvLock = "adv_lock_"
_prefixAdvance = "cache:AdvanceComment:"
_prefixHis = "dm_his_%d_%d_%d"
_prefixHisIdx = "dm_his_idx_%d_%d_%s"
_prefixDMMask = "dm_mask_%d_%d_%d"
)
func keyMsgPubLock(mid, color, rnd int64, mode, fontsize int32, ip, msg string) string {
crcStr := fmt.Sprintf("%d_%s_%s_%d_%d_%d_%d", mid, msg, ip, fontsize, color, mode, rnd)
return _prefixPubLock + fmt.Sprint(crc32.ChecksumIEEE([]byte(crcStr)))
}
func keyOidPubLock(mid, oid int64, ip string) string {
crcStr := fmt.Sprintf("%d_%s_%d", mid, ip, oid)
return _prefixPubLock + fmt.Sprint(crc32.ChecksumIEEE([]byte(crcStr)))
}
func keyPubCntLock(mid, color int64, mode, fontsize int32, ip, msg string) string {
crcStr := fmt.Sprintf("%d_%s_%s_%d_%d_%d", mid, msg, ip, fontsize, color, mode)
return _prefixPubLock + fmt.Sprint(crc32.ChecksumIEEE([]byte(crcStr)))
}
func keyCharPubLock(mid, oid int64) string {
return _prefixCharPubLock + fmt.Sprintf("%d_%d", mid, oid)
}
func keyXML(oid int64) string {
return _prefixXML + strconv.FormatInt(oid, 10)
}
func keySubject(tp int32, oid int64) string {
return _prefixSub + fmt.Sprintf("%d_%d", tp, oid)
}
func keyAjax(oid int64) string {
return _prefixAjax + strconv.FormatInt(oid, 10)
}
func keyJudge(tp int8, oid, dmid int64) string {
return fmt.Sprintf(_prefixDMJudge, tp, oid, dmid)
}
func keyDMLimitMid(mid int64) string {
return _prefixDMLimit + strconv.FormatInt(mid, 10)
}
func keyAdvanceCmt(mid, oid int64, mode string) string {
return fmt.Sprintf(_prefixAdvanceCmt, mid, oid, mode)
}
func keyAdvLock(mid, cid int64) string {
return _prefixAdvLock + strconv.FormatInt(mid, 10) + "_" + strconv.FormatInt(cid, 10)
}
func keyHistory(tp int32, oid, timestamp int64) string {
return fmt.Sprintf(_prefixHis, tp, oid, timestamp)
}
func keyHistoryIdx(tp int32, oid int64, month string) string {
return fmt.Sprintf(_prefixHisIdx, tp, oid, month)
}
func keyDMMask(tp int32, oid int64, plat int8) string {
return fmt.Sprintf(_prefixDMMask, tp, oid, plat)
}
// SubjectCache get subject from memcache.
func (d *Dao) SubjectCache(c context.Context, tp int32, oid int64) (sub *model.Subject, err error) {
var (
conn = d.dmMC.Get(c)
key = keySubject(tp, oid)
rp *memcache.Item
)
defer conn.Close()
if rp, err = conn.Get(key); err != nil {
if err == memcache.ErrNotFound {
PromCacheMiss("dm_subject", 1)
sub = nil
err = nil
} else {
log.Error("mc.Get(%s) error(%v)", key, err)
}
return
}
sub = &model.Subject{}
PromCacheHit("dm_subject", 1)
if err = conn.Scan(rp, &sub); err != nil {
log.Error("mc.Scan() error(%v)", err)
}
return
}
// SubjectsCache multi get subject from memcache.
func (d *Dao) SubjectsCache(c context.Context, tp int32, oids []int64) (cached map[int64]*model.Subject, missed []int64, err error) {
var (
conn = d.dmMC.Get(c)
keys []string
oidMap = make(map[string]int64)
)
cached = make(map[int64]*model.Subject)
defer conn.Close()
for _, oid := range oids {
k := keySubject(tp, oid)
if _, ok := oidMap[k]; !ok {
keys = append(keys, k)
oidMap[k] = oid
}
}
rs, err := conn.GetMulti(keys)
if err != nil {
log.Error("conn.GetMulti(%v) error(%v)", keys, err)
return
}
for k, r := range rs {
sub := &model.Subject{}
if err = conn.Scan(r, sub); err != nil {
log.Error("conn.Scan(%s) error(%v)", r.Value, err)
err = nil
continue
}
cached[oidMap[k]] = sub
// delete hit key
delete(oidMap, k)
}
// missed key
missed = make([]int64, 0, len(oidMap))
for _, oid := range oidMap {
missed = append(missed, oid)
}
PromCacheHit("dm_subjects", int64(len(cached)))
PromCacheMiss("dm_subjects", int64(len(missed)))
return
}
// AddSubjectCache add subject cache.
func (d *Dao) AddSubjectCache(c context.Context, sub *model.Subject) (err error) {
var (
conn = d.dmMC.Get(c)
key = keySubject(sub.Type, sub.Oid)
)
defer conn.Close()
item := &memcache.Item{
Key: key,
Object: sub,
Flags: memcache.FlagJSON,
Expiration: d.subjectExpire,
}
if err = conn.Set(item); err != nil {
log.Error("conn.Set(%v) error(%v)", item, err)
}
return
}
// DelXMLCache delete xml content.
func (d *Dao) DelXMLCache(c context.Context, oid int64) (err error) {
conn := d.dmMC.Get(c)
if err = conn.Delete(keyXML(oid)); err != nil {
if err == memcache.ErrNotFound {
err = nil
} else {
log.Error("conn.Delete(%s) error(%v)", keyXML(oid), err)
}
}
conn.Close()
return
}
// AddXMLCache add xml content to memcache.
func (d *Dao) AddXMLCache(c context.Context, oid int64, value []byte) (err error) {
conn := d.dmMC.Get(c)
defer conn.Close()
item := &memcache.Item{
Key: keyXML(oid),
Value: value,
Expiration: d.dmExpire,
}
if err = conn.Set(item); err != nil {
log.Error("conn.Set(%s) error(%v)", keyXML(oid), err)
}
return
}
// XMLCache get xml content.
func (d *Dao) XMLCache(c context.Context, oid int64) (data []byte, err error) {
key := keyXML(oid)
conn := d.dmMC.Get(c)
defer conn.Close()
item, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
PromCacheMiss("dm_xml", 1)
} else {
log.Error("mc.Get(%s) error(%v)", key, err)
}
return
}
PromCacheHit("dm_xml", 1)
data = item.Value
return
}
// AjaxDMCache get ajax dm from memcache.
func (d *Dao) AjaxDMCache(c context.Context, oid int64) (msgs []string, err error) {
conn := d.dmMC.Get(c)
defer conn.Close()
key := keyAjax(oid)
msgs = make([]string, 0)
item, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
PromCacheMiss("dm_ajax", 1)
} else {
log.Error("conn.Get(%s) error(%v)", key, err)
}
return
}
PromCacheHit("dm_ajax", 1)
if err = conn.Scan(item, &msgs); err != nil {
log.Error("conn.Scan(%v) error(%v)", item, err)
}
return
}
// AddAjaxDMCache set ajax dm to memcache.
func (d *Dao) AddAjaxDMCache(c context.Context, oid int64, msgs []string) (err error) {
conn := d.dmMC.Get(c)
defer conn.Close()
key := keyAjax(oid)
item := &memcache.Item{Key: key, Object: msgs, Flags: memcache.FlagJSON, Expiration: d.ajaxExpire}
if err = conn.Set(item); err != nil {
log.Error("conn.Set(%v) error(%v)", item, err)
}
return
}
// SetDMJudgeCache dm fengjiwei list
func (d *Dao) SetDMJudgeCache(c context.Context, tp int8, oid, dmid int64, l *model.JudgeDMList) (err error) {
key := keyJudge(tp, oid, dmid)
conn := d.dmMC.Get(c)
defer conn.Close()
item := memcache.Item{
Key: key,
Object: l,
Expiration: 86400 * 30,
Flags: memcache.FlagJSON,
}
if err = conn.Set(&item); err != nil {
log.Error("DMJudge:mc.Set(%v) error(%v)", item, err)
}
return
}
// DMJudgeCache memcache cache of dm judge list.
func (d *Dao) DMJudgeCache(c context.Context, tp int8, oid, dmid int64) (l *model.JudgeDMList, err error) {
key := keyJudge(tp, oid, dmid)
conn := d.dmMC.Get(c)
defer conn.Close()
item, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
l = nil
PromCacheMiss("dm_judge", 1)
} else {
log.Error("mc.Get(key:%s) error(%v)", key, err)
}
return
}
PromCacheHit("dm_judge", 1)
if err = conn.Scan(item, &l); err != nil {
log.Error("conn.Scan(%v) error(%v)", item, err)
}
return
}
// AddMsgPubLock set publock into memcache
func (d *Dao) AddMsgPubLock(c context.Context, mid, color, rnd int64, mode, fontsize int32, ip, msg string) (err error) {
conn := d.dmMC.Get(c)
item := memcache.Item{
Key: keyMsgPubLock(mid, color, rnd, mode, fontsize, ip, msg),
Value: _lockvalue,
Expiration: 300,
Flags: memcache.FlagRAW,
}
if err = conn.Set(&item); err != nil {
log.Error("mc.Set(%v) error(%v)", item, err)
}
conn.Close()
return
}
// MsgPublock get publock
func (d *Dao) MsgPublock(c context.Context, mid, color, rnd int64, mode, fontsize int32, ip, msg string) (cached bool, err error) {
conn := d.dmMC.Get(c)
defer conn.Close()
key := keyMsgPubLock(mid, color, rnd, mode, fontsize, ip, msg)
if _, err = conn.Get(key); err != nil {
if err == memcache.ErrNotFound {
cached = false
err = nil
} else {
log.Error("mc.Get(%s) error(%v)", key, err)
}
return
}
cached = true
return
}
// AddOidPubLock set publock into memcache
func (d *Dao) AddOidPubLock(c context.Context, mid, oid int64, ip string) (err error) {
conn := d.dmMC.Get(c)
item := memcache.Item{
Key: keyOidPubLock(mid, oid, ip),
Value: _lockvalue,
Expiration: 4,
Flags: memcache.FlagRAW,
}
if err = conn.Set(&item); err != nil {
log.Error("mc.Set(%v) error(%v)", item, err)
}
conn.Close()
return
}
// OidPubLock get publock
func (d *Dao) OidPubLock(c context.Context, mid, oid int64, ip string) (cached bool, err error) {
conn := d.dmMC.Get(c)
defer conn.Close()
key := keyOidPubLock(mid, oid, ip)
if _, err = conn.Get(key); err != nil {
if err == memcache.ErrNotFound {
cached = false
err = nil
} else {
log.Error("mc.Get(%s) error(%v)", key, err)
}
return
}
cached = true
return
}
// AddDMLimitCache add Dmlimit in cache
func (d *Dao) AddDMLimitCache(c context.Context, mid int64, limiter *model.Limiter) (err error) {
var (
conn = d.dmMC.Get(c)
key = keyDMLimitMid(mid)
)
defer conn.Close()
item := &memcache.Item{
Key: key,
Object: limiter,
Flags: memcache.FlagJSON,
Expiration: 600,
}
if err = conn.Set(item); err != nil {
log.Error("conn.Set(%v) error(%v)", item, err)
}
return
}
// DMLimitCache get dm limit from memcache.
func (d *Dao) DMLimitCache(c context.Context, mid int64) (limiter *model.Limiter, err error) {
var (
conn = d.dmMC.Get(c)
key = keyDMLimitMid(mid)
rp *memcache.Item
)
limiter = &model.Limiter{}
defer conn.Close()
if rp, err = conn.Get(key); err != nil {
if err == memcache.ErrNotFound {
limiter = nil
err = nil
} else {
log.Error("mc.Get(%s) error(%v)", key, err)
}
return
}
if err = conn.Scan(rp, &limiter); err != nil {
log.Error("mc.Scan() error(%v)", err)
}
return
}
// AddAdvanceCmtCache return
func (d *Dao) AddAdvanceCmtCache(c context.Context, oid, mid int64, mode string, adv *model.AdvanceCmt) (err error) {
var (
conn = d.filterMC.Get(c)
key = keyAdvanceCmt(mid, oid, mode)
)
defer conn.Close()
item := &memcache.Item{
Key: key,
Object: adv,
Flags: memcache.FlagJSON,
Expiration: d.filterMCExpire,
}
if err = conn.Set(item); err != nil {
log.Error("conn.Set(%v) error(%v)", item, err)
}
return
}
// AdvanceCmtCache return advance comment from memcache.
func (d *Dao) AdvanceCmtCache(c context.Context, oid, mid int64, mode string) (adv *model.AdvanceCmt, err error) {
var (
conn = d.filterMC.Get(c)
key = keyAdvanceCmt(mid, oid, mode)
rp *memcache.Item
)
defer conn.Close()
adv = &model.AdvanceCmt{}
if rp, err = conn.Get(key); err != nil {
if err == memcache.ErrNotFound {
adv = nil
err = nil
PromCacheMiss("dm_advance", 1)
} else {
log.Error("mc.Get(%s) error(%v)", key, err)
}
return
}
PromCacheHit("dm_advance", 1)
if err = conn.Scan(rp, &adv); err != nil {
log.Error("mc.Scan() error(%v)", err)
}
return
}
// AddAdvanceLock 购买高级弹幕锁
func (d *Dao) AddAdvanceLock(c context.Context, mid, cid int64) (succeed bool) {
var (
key = keyAdvLock(mid, cid)
conn = d.filterMC.Get(c)
)
defer conn.Close()
item := &memcache.Item{
Key: key,
Value: []byte("3"),
Expiration: 60,
}
if err := conn.Add(item); err != nil {
succeed = false
log.Error("conn.Add(%s) error(%v)", key, err)
} else {
succeed = true
}
return
}
// DelAdvanceLock 删除购买高级弹幕锁
func (d *Dao) DelAdvanceLock(c context.Context, mid, cid int64) (err error) {
var (
key = keyAdvLock(mid, cid)
conn = d.filterMC.Get(c)
)
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
} else {
log.Error("conn.Delete(%s) error(%v)", key, err)
}
}
conn.Close()
return
}
// DelAdvCache delete from cache.
func (d *Dao) DelAdvCache(c context.Context, mid, cid int64, mode string) (err error) {
var (
key = _prefixAdvance + strconv.FormatInt(mid, 10) + "@" + strconv.FormatInt(cid, 10) + "." + mode
)
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
}
// AddHistoryCache add dm history to memcache.
func (d *Dao) AddHistoryCache(c context.Context, tp int32, oid, timestamp int64, value []byte) (err error) {
var (
conn = d.dmMC.Get(c)
key = keyHistory(tp, oid, timestamp)
)
defer conn.Close()
item := &memcache.Item{
Key: key,
Value: value,
Expiration: d.historyExpire,
}
if err = conn.Set(item); err != nil {
log.Error("conn.Set(%s) error(%v)", key, err)
}
return
}
// HistoryCache history cache.
func (d *Dao) HistoryCache(c context.Context, tp int32, oid, timestamp int64) (data []byte, err error) {
var (
conn = d.dmMC.Get(c)
key = keyHistory(tp, oid, timestamp)
)
defer conn.Close()
item, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
PromCacheMiss("dm_history", 1)
} else {
log.Error("mc.Get(%s) error(%v)", key, err)
}
return
}
PromCacheHit("dm_history", 1)
data = item.Value
return
}
// AddHisIdxCache add dm history date index to memcache.
func (d *Dao) AddHisIdxCache(c context.Context, tp int32, oid int64, month string, dates []string) (err error) {
var (
conn = d.dmMC.Get(c)
key = keyHistoryIdx(tp, oid, month)
)
defer conn.Close()
item := &memcache.Item{
Key: key,
Object: dates,
Flags: memcache.FlagJSON,
Expiration: d.historyExpire,
}
if err = conn.Set(item); err != nil {
log.Error("conn.Set(%s) error(%v)", key, err)
}
return
}
// HistoryIdxCache get history date index.
func (d *Dao) HistoryIdxCache(c context.Context, tp int32, oid int64, month string) (dates []string, err error) {
var (
conn = d.dmMC.Get(c)
key = keyHistoryIdx(tp, oid, month)
)
defer conn.Close()
item, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
PromCacheMiss("dm_history_index", 1)
} else {
log.Error("mc.Get(%s) error(%v)", key, err)
}
return
}
PromCacheHit("dm_history_index", 1)
if err = conn.Scan(item, &dates); err != nil {
log.Error("conn.Scan(%+v) error(%v)", item, err)
}
return
}
// DMMaskCache get dm mask cache
func (d *Dao) DMMaskCache(c context.Context, tp int32, oid int64, plat int8) (mask *model.Mask, err error) {
var (
conn = d.dmMC.Get(c)
key = keyDMMask(tp, oid, plat)
item *memcache.Item
)
defer conn.Close()
if item, err = conn.Get(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
mask = nil
PromCacheMiss("dm_mask", 1)
} else {
log.Error("mc.Get(%s) error(%v)", key, err)
}
return
}
mask = &model.Mask{}
PromCacheHit("dm_mask", 1)
if err = conn.Scan(item, &mask); err != nil {
log.Error("conn.Scan(%+v) error(%v)", item, err)
}
return
}
// AddMaskCache add dm mask cache
func (d *Dao) AddMaskCache(c context.Context, tp int32, mask *model.Mask) (err error) {
var (
conn = d.dmMC.Get(c)
key = keyDMMask(tp, mask.Cid, mask.Plat)
)
defer conn.Close()
item := &memcache.Item{
Key: key,
Object: mask,
Flags: memcache.FlagJSON,
Expiration: d.dmMaskExpire,
}
if err = conn.Set(item); err != nil {
log.Error("conn.Set(%+v) error(%v)", item, err)
}
return
}

View File

@@ -0,0 +1,217 @@
package dao
import (
"context"
"encoding/json"
"strconv"
"go-common/app/interface/main/dm2/model"
"go-common/library/cache/memcache"
"go-common/library/log"
)
const (
_prefixUpFilter = "filter_up_"
_prefixUserFilter = "filter_user_"
_prefixGlobalFilter = "filter_global"
)
func keyUserFilter(mid int64) string {
return _prefixUserFilter + strconv.FormatInt(mid, 10)
}
func keyUpFilter(mid int64) string {
return _prefixUpFilter + strconv.FormatInt(mid, 10)
}
func keyGlobalFilter() string {
return _prefixGlobalFilter
}
// AddUserFilterCache set user filters into cache.
func (d *Dao) AddUserFilterCache(c context.Context, mid int64, data []*model.UserFilter) (err error) {
bs, err := json.Marshal(data)
if err != nil {
log.Error("json.Marshal() error(%v)", err)
return
}
key := keyUserFilter(mid)
conn := d.filterMC.Get(c)
item := &memcache.Item{
Key: key,
Value: bs,
Expiration: d.filterMCExpire,
}
if err = conn.Set(item); err != nil {
log.Error("memcache.Set(%v) error(%v)", item, err)
}
conn.Close()
return
}
// DelUserFilterCache delete user filters from cache.
func (d *Dao) DelUserFilterCache(c context.Context, mid int64) (err error) {
var (
key = keyUserFilter(mid)
conn = d.filterMC.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
}
// UserFilterCache get user filters from cache.
func (d *Dao) UserFilterCache(c context.Context, mid int64) (data []*model.UserFilter, err error) {
var (
key = keyUserFilter(mid)
conn = d.filterMC.Get(c)
item *memcache.Item
)
defer conn.Close()
if item, err = conn.Get(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
data = nil
PromCacheMiss("user_filter", 1)
} else {
log.Error("memcache.Get(%s) error(%v)", key, err)
}
return
}
PromCacheHit("user_filter", 1)
if e := json.Unmarshal(item.Value, &data); e != nil {
log.Error("json.Unmarshal(%s) error(%v)", item.Value, e)
}
return
}
// AddUpFilterCache add upper filter cache.
func (d *Dao) AddUpFilterCache(c context.Context, mid int64, data []*model.UpFilter) (err error) {
var (
conn = d.filterMC.Get(c)
key = keyUpFilter(mid)
)
defer conn.Close()
item := &memcache.Item{
Key: key,
Object: data,
Flags: memcache.FlagJSON | memcache.FlagGzip,
Expiration: d.filterMCExpire,
}
if err = conn.Set(item); err != nil {
log.Error("conn.Set(%v) error(%v)", item, err)
}
return
}
// DelUpFilterCache delete up filters from cache.
func (d *Dao) DelUpFilterCache(c context.Context, mid int64) (err error) {
key := keyUpFilter(mid)
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
}
// UpFilterCache get user filter from memcache.
func (d *Dao) UpFilterCache(c context.Context, mid int64) (data []*model.UpFilter, err error) {
var (
conn = d.filterMC.Get(c)
key = keyUpFilter(mid)
rp *memcache.Item
)
defer conn.Close()
data = make([]*model.UpFilter, 0)
if rp, err = conn.Get(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
PromCacheMiss("upper_filter", 1)
} else {
log.Error("mc.Get(%s) error(%v)", key, err)
}
return
}
PromCacheHit("upper_filter", 1)
if err = conn.Scan(rp, &data); err != nil {
log.Error("mc.Scan() error(%v)", err)
}
return
}
// AddGlobalFilterCache set global rules into cache.
func (d *Dao) AddGlobalFilterCache(c context.Context, data []*model.GlobalFilter) (err error) {
var (
value []byte
key = keyGlobalFilter()
conn = d.filterMC.Get(c)
)
defer conn.Close()
if value, err = json.Marshal(data); err != nil {
log.Error("json.Marshal(%v) error(%v)", data, err)
return
}
item := &memcache.Item{
Key: key,
Value: value,
Expiration: d.filterMCExpire,
}
if err = conn.Set(item); err != nil {
log.Error("memcache.Set(%v) error(%v)", item, err)
}
return
}
// DelGlobalFilterCache delete global rules from cache.
func (d *Dao) DelGlobalFilterCache(c context.Context) (err error) {
var (
key = keyGlobalFilter()
conn = d.filterMC.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
}
// GlobalFilterCache get up filters from cache.
func (d *Dao) GlobalFilterCache(c context.Context) (data []*model.GlobalFilter, err error) {
var (
key = keyGlobalFilter()
conn = d.filterMC.Get(c)
item *memcache.Item
)
defer conn.Close()
if item, err = conn.Get(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
data = nil
PromCacheMiss("global_filter", 1)
} else {
log.Error("memcache.Get(%s) error(%v)", key, err)
}
return
}
PromCacheHit("global_filter", 1)
if e := json.Unmarshal(item.Value, &data); e != nil {
log.Error("json.Unmarshal(%s) error(%v)", item.Value, e)
}
return
}

View File

@@ -0,0 +1,178 @@
package dao
import (
"context"
"go-common/app/interface/main/dm2/model"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaokeyUserFilter(t *testing.T) {
convey.Convey("keyUserFilter", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyUserFilter(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaokeyUpFilter(t *testing.T) {
convey.Convey("keyUpFilter", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyUpFilter(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaokeyGlobalFilter(t *testing.T) {
convey.Convey("keyGlobalFilter", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyGlobalFilter()
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoAddUserFilterCache(t *testing.T) {
convey.Convey("AddUserFilterCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
data = []*model.UserFilter{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.AddUserFilterCache(c, mid, data)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoDelUserFilterCache(t *testing.T) {
convey.Convey("DelUserFilterCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.DelUserFilterCache(c, mid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoUserFilterCache(t *testing.T) {
convey.Convey("UserFilterCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.UserFilterCache(c, mid)
})
})
}
func TestDaoAddUpFilterCache(t *testing.T) {
convey.Convey("AddUpFilterCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
data = []*model.UpFilter{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.AddUpFilterCache(c, mid, data)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoDelUpFilterCache(t *testing.T) {
convey.Convey("DelUpFilterCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.DelUpFilterCache(c, mid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoUpFilterCache(t *testing.T) {
convey.Convey("UpFilterCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
data, err := testDao.UpFilterCache(c, mid)
ctx.Convey("Then err should be nil.data should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(data, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoAddGlobalFilterCache(t *testing.T) {
convey.Convey("AddGlobalFilterCache", t, func(ctx convey.C) {
var (
c = context.Background()
data = []*model.GlobalFilter{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.AddGlobalFilterCache(c, data)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoDelGlobalFilterCache(t *testing.T) {
convey.Convey("DelGlobalFilterCache", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.DelGlobalFilterCache(c)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoGlobalFilterCache(t *testing.T) {
convey.Convey("GlobalFilterCache", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.GlobalFilterCache(c)
})
})
}

View File

@@ -0,0 +1,61 @@
package dao
import (
"context"
"strconv"
"go-common/app/interface/main/dm2/model"
"go-common/library/cache/memcache"
"go-common/library/log"
)
const (
_prefixDmDailyLimit = "dm_daily_limit_"
)
func keyDmDailyLimit(mid int64) string {
return _prefixDmDailyLimit + strconv.FormatInt(mid, 10)
}
// SetDmDailyLimitCache .
func (d *Dao) SetDmDailyLimitCache(c context.Context, mid int64, limiter *model.DailyLimiter) (err error) {
var (
conn = d.dmSegMC.Get(c)
key = keyDmDailyLimit(mid)
)
defer conn.Close()
item := &memcache.Item{
Key: key,
Object: limiter,
Flags: memcache.FlagJSON,
Expiration: d.dmLimiterMCExpire,
}
if err = conn.Set(item); err != nil {
log.Error("conn.Set(%v) error(%v)", item, err)
}
return
}
// GetDmDailyLimitCache .
func (d *Dao) GetDmDailyLimitCache(c context.Context, mid int64) (limiter *model.DailyLimiter, err error) {
var (
conn = d.dmSegMC.Get(c)
key = keyDmDailyLimit(mid)
rp *memcache.Item
)
defer conn.Close()
if rp, err = conn.Get(key); err != nil {
if err == memcache.ErrNotFound {
limiter = nil
err = nil
} else {
log.Error("mc.Get(%s) error(%v)", key, err)
}
return
}
limiter = &model.DailyLimiter{}
if err = conn.Scan(rp, &limiter); err != nil {
log.Error("mc.Scan() error(%v)", err)
}
return
}

View File

@@ -0,0 +1,55 @@
package dao
import (
"context"
"go-common/app/interface/main/dm2/model"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaokeyDmDailyLimit(t *testing.T) {
convey.Convey("keyDmDailyLimit", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyDmDailyLimit(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoSetDmDailyLimitCache(t *testing.T) {
convey.Convey("SetDmDailyLimitCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
limiter = &model.DailyLimiter{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.SetDmDailyLimitCache(c, mid, limiter)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoGetDmDailyLimitCache(t *testing.T) {
convey.Convey("GetDmDailyLimitCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
limiter, err := testDao.GetDmDailyLimitCache(c, mid)
ctx.Convey("Then err should be nil.limiter should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(limiter, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,153 @@
package dao
import (
"context"
"fmt"
"strconv"
"go-common/app/interface/main/dm2/model"
"go-common/library/cache/memcache"
"go-common/library/log"
)
const (
_keyDuration = "d_" // video duration
_keySegMC = "sg_%d_%d_%d_%d"
)
func keyXMLSeg(tp int32, oid, cnt, num int64) string {
return fmt.Sprintf("%d_%d_%d_%d", tp, oid, cnt, num)
}
func keySegMC(tp int32, oid, total, num int64) string {
return fmt.Sprintf(_keySegMC, tp, oid, total, num)
}
// keyDuration return video duration key.
func keyDuration(oid int64) string {
return _keyDuration + strconv.FormatInt(oid, 10)
}
// XMLSegCache get dm segment xml content from memcache.
func (d *Dao) XMLSegCache(c context.Context, tp int32, oid, cnt, num int64) (res []byte, err error) {
var (
conn = d.dmMC.Get(c)
key = keyXMLSeg(tp, oid, cnt, num)
rp *memcache.Item
)
defer conn.Close()
if rp, err = conn.Get(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
PromCacheMiss("dm_xml_seg", 1)
} else {
log.Error("mc.Get(%s) error(%v)", key, err)
}
return
}
PromCacheHit("dm_xml_seg", 1)
if err = conn.Scan(rp, &res); err != nil {
log.Error("mc.Scan() error(%v)", err)
}
return
}
// SetXMLSegCache set dm xml content into memcache.
func (d *Dao) SetXMLSegCache(c context.Context, tp int32, oid, cnt, num int64, value []byte) (err error) {
key := keyXMLSeg(tp, oid, cnt, num)
conn := d.dmMC.Get(c)
item := memcache.Item{
Key: key,
Value: value,
Expiration: d.dmExpire,
Flags: memcache.FlagRAW,
}
if err = conn.Set(&item); err != nil {
log.Error("mc.Set(%v) error(%v)", item, err)
}
conn.Close()
return
}
// DurationCache return duration of video.
func (d *Dao) DurationCache(c context.Context, oid int64) (duration int64, err error) {
var (
key = keyDuration(oid)
conn = d.dmMC.Get(c)
item *memcache.Item
)
defer conn.Close()
if item, err = conn.Get(key); err != nil {
if err == memcache.ErrNotFound {
duration = model.NotFound
err = nil
PromCacheMiss("video_duration", 1)
} else {
log.Error("conn.Get(%s) error(%v)", key, err)
}
return
}
PromCacheHit("video_duration", 1)
if duration, err = strconv.ParseInt(string(item.Value), 10, 64); err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", item.Value, err)
}
return
}
// SetDurationCache set video duration to redis.
func (d *Dao) SetDurationCache(c context.Context, oid, duration int64) (err error) {
key := keyDuration(oid)
conn := d.dmMC.Get(c)
item := memcache.Item{
Key: key,
Value: []byte(fmt.Sprint(duration)),
Expiration: d.dmExpire,
Flags: memcache.FlagRAW,
}
if err = conn.Set(&item); err != nil {
log.Error("mc.Set(%v) error(%v)", item, err)
}
conn.Close()
return
}
// SetDMSegCache set segment dm to cache.
func (d *Dao) SetDMSegCache(c context.Context, tp int32, oid, total, num int64, dmSeg *model.DMSeg) (err error) {
key := keySegMC(tp, oid, total, num)
conn := d.dmSegMC.Get(c)
item := memcache.Item{
Key: key,
Object: dmSeg,
Expiration: d.dmSegMCExpire,
Flags: memcache.FlagProtobuf | memcache.FlagGzip,
}
if err = conn.Set(&item); err != nil {
log.Error("conn.Set(%v) error(%v)", item, err)
}
conn.Close()
return
}
// DMSegCache dm segment pb cache.
func (d *Dao) DMSegCache(c context.Context, tp int32, oid, total, num int64) (dmSeg *model.DMSeg, err error) {
var (
key = keySegMC(tp, oid, total, num)
conn = d.dmSegMC.Get(c)
item *memcache.Item
)
dmSeg = new(model.DMSeg)
defer conn.Close()
if item, err = conn.Get(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
dmSeg = nil
} else {
log.Error("mc.Get(%s) error(%v)", key, err)
}
return
}
if err = conn.Scan(item, dmSeg); err != nil {
log.Error("conn.Scan() error(%v)", err)
}
return
}

View File

@@ -0,0 +1,66 @@
package dao
import (
"context"
"testing"
"go-common/app/interface/main/dm2/model"
. "github.com/smartystreets/goconvey/convey"
)
func TestSetXMLSegCache(t *testing.T) {
Convey("", t, func() {
err := testDao.SetXMLSegCache(context.TODO(), model.SubTypeVideo, 1221, 1, 1, []byte("test"))
So(err, ShouldBeNil)
})
}
func TestXMLSegCache(t *testing.T) {
Convey("", t, func() {
_, err := testDao.XMLSegCache(context.TODO(), model.SubTypeVideo, 1221, 1, 1)
So(err, ShouldBeNil)
})
}
func TestDurationCache(t *testing.T) {
var (
oid int64 = 1508
c = context.TODO()
)
Convey("", t, func() {
_, err := testDao.DurationCache(c, oid)
So(err, ShouldBeNil)
})
}
func TestSetDurationCache(t *testing.T) {
var (
oid int64 = 1508
duration int64 = 9031 * 1000
c = context.TODO()
)
Convey("", t, func() {
err := testDao.SetDurationCache(c, oid, duration)
So(err, ShouldBeNil)
})
}
func TestSetDMSegCache(t *testing.T) {
Convey("set dm segment cache, error should be nil", t, func() {
dmseg := new(model.DMSeg)
dmseg.Elems = append(dmseg.Elems, &model.Elem{Content: "dm msg"})
err := testDao.SetDMSegCache(c, 1, 1221, 1, 1, dmseg)
So(err, ShouldBeNil)
})
}
func TestDMSegCache(t *testing.T) {
Convey("get dm segment cache", t, func() {
dmseg, err := testDao.DMSegCache(c, 1, 1221, 1, 1)
if err != nil {
t.Fatal(err)
}
t.Logf("%+v", dmseg)
})
}

View File

@@ -0,0 +1,361 @@
package dao
import (
"context"
"fmt"
"go-common/app/interface/main/dm2/model"
"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"
_fmtSubtitleReportTag = "s_subtitle_report_%d_%d" // s_subtitle_report_bid_rid
)
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)
}
func (d *Dao) subtitleReportTagKey(bid, rid int64) string {
return fmt.Sprintf(_fmtSubtitleReportTag, bid, rid)
}
// SetVideoSubtitleCache .
func (d *Dao) SetVideoSubtitleCache(c context.Context, oid int64, tp int32, res *model.VideoSubtitleCache) (err error) {
var (
item *memcache.Item
conn = d.subtitleMc.Get(c)
key = d.subtitleVideoKey(oid, tp)
)
defer conn.Close()
item = &memcache.Item{
Key: key,
Object: res,
Flags: memcache.FlagJSON | memcache.FlagGzip,
Expiration: d.subtitleMcExpire,
}
if err = conn.Set(item); err != nil {
log.Error("conn.Set(%v) error(%v)", item, err)
}
return
}
// VideoSubtitleCache .
func (d *Dao) VideoSubtitleCache(c context.Context, oid int64, tp int32) (res *model.VideoSubtitleCache, err error) {
var (
item *memcache.Item
conn = d.subtitleMc.Get(c)
key = d.subtitleVideoKey(oid, tp)
)
defer conn.Close()
if item, err = conn.Get(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
res = nil
return
}
log.Error("memcache.Get(%s) error(%v)", key, err)
return
}
if err = conn.Scan(item, &res); err != nil {
log.Error("mc.Scan() error(%v)", err)
}
return
}
// 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
}
// SubtitleDraftCache .
func (d *Dao) SubtitleDraftCache(c context.Context, oid int64, tp int32, mid int64, lan uint8) (subtitle *model.Subtitle, err error) {
var (
item *memcache.Item
conn = d.subtitleMc.Get(c)
key = d.subtitleDraftKey(oid, tp, mid, lan)
)
defer conn.Close()
if item, err = conn.Get(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
} else {
log.Error("memcache.Get(%s) error(%v)", key, err)
}
return
}
if err = conn.Scan(item, &subtitle); err != nil {
log.Error("mc.Scan() error(%v)", err)
}
return
}
// SetSubtitleDraftCache .
func (d *Dao) SetSubtitleDraftCache(c context.Context, subtitle *model.Subtitle) (err error) {
var (
item *memcache.Item
conn = d.subtitleMc.Get(c)
key = d.subtitleDraftKey(subtitle.Oid, subtitle.Type, subtitle.Mid, subtitle.Lan)
)
defer conn.Close()
item = &memcache.Item{
Key: key,
Object: subtitle,
Flags: memcache.FlagJSON | memcache.FlagGzip,
Expiration: d.subtitleMcExpire,
}
if err = conn.Set(item); err != nil {
log.Error("conn.Set(%v) error(%v)", item, 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
}
// SubtitlesCache .
func (d *Dao) SubtitlesCache(c context.Context, oid int64, subtitleIds []int64) (res map[int64]*model.Subtitle, missed []int64, err error) {
var (
conn = d.subtitleMc.Get(c)
keys []string
subtitleIDMap = make(map[string]int64)
)
res = make(map[int64]*model.Subtitle)
defer conn.Close()
for _, subtitleID := range subtitleIds {
k := d.subtitleKey(oid, subtitleID)
if _, ok := subtitleIDMap[k]; !ok {
keys = append(keys, k)
subtitleIDMap[k] = subtitleID
}
}
rs, err := conn.GetMulti(keys)
if err != nil {
log.Error("conn.GetMulti(%v) error(%v)", keys, err)
return
}
for k, r := range rs {
st := &model.Subtitle{}
if err = conn.Scan(r, st); err != nil {
log.Error("conn.Scan(%s) error(%v)", r.Value, err)
err = nil
continue
}
res[subtitleIDMap[k]] = st
// delete hit key
delete(subtitleIDMap, k)
}
// missed key
missed = make([]int64, 0, len(subtitleIDMap))
for _, subtitleID := range subtitleIDMap {
missed = append(missed, subtitleID)
}
return
}
// SubtitleCache .
func (d *Dao) SubtitleCache(c context.Context, oid int64, subtitleID int64) (subtitle *model.Subtitle, err error) {
var (
item *memcache.Item
conn = d.subtitleMc.Get(c)
key = d.subtitleKey(oid, subtitleID)
)
defer conn.Close()
if item, err = conn.Get(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
} else {
log.Error("memcache.Get(%s) error(%v)", key, err)
}
return
}
if err = conn.Scan(item, &subtitle); err != nil {
log.Error("mc.Scan() error(%v)", err)
}
return
}
// SetSubtitleCache .
func (d *Dao) SetSubtitleCache(c context.Context, subtitle *model.Subtitle) (err error) {
var (
item *memcache.Item
conn = d.subtitleMc.Get(c)
key = d.subtitleKey(subtitle.Oid, subtitle.ID)
)
defer conn.Close()
item = &memcache.Item{
Key: key,
Object: subtitle,
Flags: memcache.FlagJSON | memcache.FlagGzip,
Expiration: d.subtitleMcExpire,
}
if err = conn.Set(item); err != nil {
log.Error("conn.Set(%v) error(%v)", item, 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
}
// SetSubtitleSubjectCache .
func (d *Dao) SetSubtitleSubjectCache(c context.Context, subtitleSubject *model.SubtitleSubject) (err error) {
var (
key = d.subtitleSubjectKey(subtitleSubject.Aid)
conn = d.subtitleMc.Get(c)
item *memcache.Item
)
defer conn.Close()
item = &memcache.Item{
Key: key,
Object: subtitleSubject,
Flags: memcache.FlagJSON | memcache.FlagGzip,
Expiration: d.subtitleMcExpire,
}
if err = conn.Set(item); err != nil {
log.Error("conn.Set(%v) error(%v)", item, err)
}
return
}
// SubtitleSubjectCache .
func (d *Dao) SubtitleSubjectCache(c context.Context, aid int64) (subtitleSubject *model.SubtitleSubject, err error) {
var (
item *memcache.Item
conn = d.subtitleMc.Get(c)
key = d.subtitleSubjectKey(aid)
)
defer conn.Close()
if item, err = conn.Get(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
} else {
log.Error("memcache.Get(%s) error(%v)", key, err)
}
return
}
if err = conn.Scan(item, &subtitleSubject); err != nil {
log.Error("mc.Scan() error(%v)", 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
}
// SubtitleWorlFlowTagCache .
func (d *Dao) SubtitleWorlFlowTagCache(c context.Context, bid, rid int64) (data []*model.WorkFlowTag, err error) {
var (
item *memcache.Item
key = d.subtitleReportTagKey(bid, rid)
conn = d.subtitleMc.Get(c)
)
defer conn.Close()
if item, err = conn.Get(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
} else {
log.Error("memcache.Get(%s) error(%v)", key, err)
}
return
}
if err = conn.Scan(item, &data); err != nil {
log.Error("mc.Scan() error(%v)", err)
}
return
}
// SetSubtitleWorlFlowTagCache .
func (d *Dao) SetSubtitleWorlFlowTagCache(c context.Context, bid, rid int64, data []*model.WorkFlowTag) (err error) {
var (
key = d.subtitleReportTagKey(bid, rid)
conn = d.subtitleMc.Get(c)
item *memcache.Item
)
defer conn.Close()
if len(data) == 0 {
return
}
item = &memcache.Item{
Key: key,
Object: data,
Flags: memcache.FlagJSON | memcache.FlagGzip,
Expiration: d.subtitleMcExpire,
}
if err = conn.Set(item); err != nil {
log.Error("conn.Set(%v) error(%v)", item, err)
}
return
}

View File

@@ -0,0 +1,321 @@
package dao
import (
"context"
"go-common/app/interface/main/dm2/model"
"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 TestDaosubtitleReportTagKey(t *testing.T) {
convey.Convey("subtitleReportTagKey", t, func(ctx convey.C) {
var (
bid = int64(0)
rid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := testDao.subtitleReportTagKey(bid, rid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoSetVideoSubtitleCache(t *testing.T) {
convey.Convey("SetVideoSubtitleCache", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
tp = int32(0)
res = &model.VideoSubtitleCache{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.SetVideoSubtitleCache(c, oid, tp, res)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoVideoSubtitleCache(t *testing.T) {
convey.Convey("VideoSubtitleCache", 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) {
res, err := testDao.VideoSubtitleCache(c, oid, tp)
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)
})
})
})
}
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) {
err := testDao.DelVideoSubtitleCache(c, oid, tp)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoSubtitleDraftCache(t *testing.T) {
convey.Convey("SubtitleDraftCache", 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.SubtitleDraftCache(c, oid, tp, mid, lan)
})
})
}
func TestDaoSetSubtitleDraftCache(t *testing.T) {
convey.Convey("SetSubtitleDraftCache", t, func(ctx convey.C) {
var (
c = context.Background()
subtitle = &model.Subtitle{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.SetSubtitleDraftCache(c, subtitle)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
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) {
err := testDao.DelSubtitleDraftCache(c, oid, tp, mid, lan)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoSubtitlesCache(t *testing.T) {
convey.Convey("SubtitlesCache", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
subtitleIds = []int64{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, missed, err := testDao.SubtitlesCache(c, oid, subtitleIds)
ctx.Convey("Then err should be nil.res,missed should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(missed, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoSubtitleCache(t *testing.T) {
convey.Convey("SubtitleCache", 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.SubtitleCache(c, oid, subtitleID)
})
})
}
func TestDaoSetSubtitleCache(t *testing.T) {
convey.Convey("SetSubtitleCache", t, func(ctx convey.C) {
var (
c = context.Background()
subtitle = &model.Subtitle{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.SetSubtitleCache(c, subtitle)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
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) {
err := testDao.DelSubtitleCache(c, oid, subtitleID)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoSetSubtitleSubjectCache(t *testing.T) {
convey.Convey("SetSubtitleSubjectCache", t, func(ctx convey.C) {
var (
c = context.Background()
subtitleSubject = &model.SubtitleSubject{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.SetSubtitleSubjectCache(c, subtitleSubject)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoSubtitleSubjectCache(t *testing.T) {
convey.Convey("SubtitleSubjectCache", 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.SubtitleSubjectCache(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)
})
})
})
}
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) {
err := testDao.DelSubtitleSubjectCache(c, aid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoSubtitleWorlFlowTagCache(t *testing.T) {
convey.Convey("SubtitleWorlFlowTagCache", t, func(ctx convey.C) {
var (
c = context.Background()
bid = int64(0)
rid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.SubtitleWorlFlowTagCache(c, bid, rid)
})
})
}
func TestDaoSetSubtitleWorlFlowTagCache(t *testing.T) {
convey.Convey("SetSubtitleWorlFlowTagCache", t, func(ctx convey.C) {
var (
c = context.Background()
bid = int64(0)
rid = int64(0)
data = []*model.WorkFlowTag{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.SetSubtitleWorlFlowTagCache(c, bid, rid, data)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,689 @@
package dao
import (
"context"
"go-common/app/interface/main/dm2/model"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaokeyMsgPubLock(t *testing.T) {
convey.Convey("keyMsgPubLock", t, func(ctx convey.C) {
var (
mid = int64(0)
color = int64(0)
rnd = int64(0)
mode = int32(0)
fontsize = int32(0)
ip = ""
msg = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyMsgPubLock(mid, color, rnd, mode, fontsize, ip, msg)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaokeyOidPubLock(t *testing.T) {
convey.Convey("keyOidPubLock", t, func(ctx convey.C) {
var (
mid = int64(0)
oid = int64(0)
ip = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyOidPubLock(mid, oid, ip)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaokeyPubCntLock(t *testing.T) {
convey.Convey("keyPubCntLock", t, func(ctx convey.C) {
var (
mid = int64(0)
color = int64(0)
mode = int32(0)
fontsize = int32(0)
ip = ""
msg = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyPubCntLock(mid, color, mode, fontsize, ip, msg)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaokeyCharPubLock(t *testing.T) {
convey.Convey("keyCharPubLock", t, func(ctx convey.C) {
var (
mid = int64(0)
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyCharPubLock(mid, oid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaokeyXML(t *testing.T) {
convey.Convey("keyXML", t, func(ctx convey.C) {
var (
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyXML(oid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaokeySubject(t *testing.T) {
convey.Convey("keySubject", t, func(ctx convey.C) {
var (
tp = int32(0)
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keySubject(tp, oid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaokeyAjax(t *testing.T) {
convey.Convey("keyAjax", t, func(ctx convey.C) {
var (
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyAjax(oid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaokeyJudge(t *testing.T) {
convey.Convey("keyJudge", t, func(ctx convey.C) {
var (
tp = int8(0)
oid = int64(0)
dmid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyJudge(tp, oid, dmid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaokeyDMLimitMid(t *testing.T) {
convey.Convey("keyDMLimitMid", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyDMLimitMid(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaokeyAdvanceCmt(t *testing.T) {
convey.Convey("keyAdvanceCmt", t, func(ctx convey.C) {
var (
mid = int64(0)
oid = int64(0)
mode = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyAdvanceCmt(mid, oid, mode)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaokeyAdvLock(t *testing.T) {
convey.Convey("keyAdvLock", t, func(ctx convey.C) {
var (
mid = int64(0)
cid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyAdvLock(mid, cid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaokeyHistory(t *testing.T) {
convey.Convey("keyHistory", t, func(ctx convey.C) {
var (
tp = int32(0)
oid = int64(0)
timestamp = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyHistory(tp, oid, timestamp)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaokeyHistoryIdx(t *testing.T) {
convey.Convey("keyHistoryIdx", t, func(ctx convey.C) {
var (
tp = int32(0)
oid = int64(0)
month = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyHistoryIdx(tp, oid, month)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaokeyDMMask(t *testing.T) {
convey.Convey("keyDMMask", t, func(ctx convey.C) {
var (
tp = int32(0)
oid = int64(0)
plat = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyDMMask(tp, oid, plat)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoSubjectCache(t *testing.T) {
convey.Convey("SubjectCache", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.SubjectCache(c, tp, oid)
})
})
}
func TestDaoSubjectsCache(t *testing.T) {
convey.Convey("SubjectsCache", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oids = []int64{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
cached, missed, err := testDao.SubjectsCache(c, tp, oids)
ctx.Convey("Then err should be nil.cached,missed should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(missed, convey.ShouldNotBeNil)
ctx.So(cached, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoAddSubjectCache(t *testing.T) {
convey.Convey("AddSubjectCache", t, func(ctx convey.C) {
var (
c = context.Background()
sub = &model.Subject{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.AddSubjectCache(c, sub)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoDelXMLCache(t *testing.T) {
convey.Convey("DelXMLCache", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.DelXMLCache(c, oid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoAddXMLCache(t *testing.T) {
convey.Convey("AddXMLCache", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
value = []byte("")
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.AddXMLCache(c, oid, value)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoXMLCache(t *testing.T) {
convey.Convey("XMLCache", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
data, err := testDao.XMLCache(c, oid)
ctx.Convey("Then err should be nil.data should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(data, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoAjaxDMCache(t *testing.T) {
convey.Convey("AjaxDMCache", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
msgs, err := testDao.AjaxDMCache(c, oid)
ctx.Convey("Then err should be nil.msgs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(msgs, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoAddAjaxDMCache(t *testing.T) {
convey.Convey("AddAjaxDMCache", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
msgs = []string{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.AddAjaxDMCache(c, oid, msgs)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoSetDMJudgeCache(t *testing.T) {
convey.Convey("SetDMJudgeCache", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int8(0)
oid = int64(0)
dmid = int64(0)
l = &model.JudgeDMList{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.SetDMJudgeCache(c, tp, oid, dmid, l)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoDMJudgeCache(t *testing.T) {
convey.Convey("DMJudgeCache", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int8(0)
oid = int64(0)
dmid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
l, err := testDao.DMJudgeCache(c, tp, oid, dmid)
ctx.Convey("Then err should be nil.l should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(l, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoAddMsgPubLock(t *testing.T) {
convey.Convey("AddMsgPubLock", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
color = int64(0)
rnd = int64(0)
mode = int32(0)
fontsize = int32(0)
ip = ""
msg = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.AddMsgPubLock(c, mid, color, rnd, mode, fontsize, ip, msg)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoMsgPublock(t *testing.T) {
convey.Convey("MsgPublock", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
color = int64(0)
rnd = int64(0)
mode = int32(0)
fontsize = int32(0)
ip = ""
msg = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
cached, err := testDao.MsgPublock(c, mid, color, rnd, mode, fontsize, ip, msg)
ctx.Convey("Then err should be nil.cached should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(cached, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoAddOidPubLock(t *testing.T) {
convey.Convey("AddOidPubLock", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
oid = int64(0)
ip = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.AddOidPubLock(c, mid, oid, ip)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoOidPubLock(t *testing.T) {
convey.Convey("OidPubLock", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
oid = int64(0)
ip = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
cached, err := testDao.OidPubLock(c, mid, oid, ip)
ctx.Convey("Then err should be nil.cached should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(cached, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoAddDMLimitCache(t *testing.T) {
convey.Convey("AddDMLimitCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
limiter = &model.Limiter{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.AddDMLimitCache(c, mid, limiter)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoDMLimitCache(t *testing.T) {
convey.Convey("DMLimitCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
limiter, err := testDao.DMLimitCache(c, mid)
ctx.Convey("Then err should be nil.limiter should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(limiter, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoAddAdvanceCmtCache(t *testing.T) {
convey.Convey("AddAdvanceCmtCache", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
mid = int64(0)
mode = ""
adv = &model.AdvanceCmt{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.AddAdvanceCmtCache(c, oid, mid, mode, adv)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoAdvanceCmtCache(t *testing.T) {
convey.Convey("AdvanceCmtCache", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
mid = int64(0)
mode = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
adv, err := testDao.AdvanceCmtCache(c, oid, mid, mode)
ctx.Convey("Then err should be nil.adv should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(adv, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoAddAdvanceLock(t *testing.T) {
convey.Convey("AddAdvanceLock", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
cid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
succeed := testDao.AddAdvanceLock(c, mid, cid)
ctx.Convey("Then succeed should not be nil.", func(ctx convey.C) {
ctx.So(succeed, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoDelAdvanceLock(t *testing.T) {
convey.Convey("DelAdvanceLock", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
cid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.DelAdvanceLock(c, mid, cid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoDelAdvCache(t *testing.T) {
convey.Convey("DelAdvCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
cid = int64(0)
mode = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.DelAdvCache(c, mid, cid, mode)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoAddHistoryCache(t *testing.T) {
convey.Convey("AddHistoryCache", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oid = int64(0)
timestamp = int64(0)
value = []byte("")
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.AddHistoryCache(c, tp, oid, timestamp, value)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoHistoryCache(t *testing.T) {
convey.Convey("HistoryCache", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oid = int64(0)
timestamp = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
data, err := testDao.HistoryCache(c, tp, oid, timestamp)
ctx.Convey("Then err should be nil.data should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(data, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoAddHisIdxCache(t *testing.T) {
convey.Convey("AddHisIdxCache", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oid = int64(0)
month = ""
dates = []string{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.AddHisIdxCache(c, tp, oid, month, dates)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoHistoryIdxCache(t *testing.T) {
convey.Convey("HistoryIdxCache", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oid = int64(0)
month = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
dates, err := testDao.HistoryIdxCache(c, tp, oid, month)
ctx.Convey("Then err should be nil.dates should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(dates, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoDMMaskCache(t *testing.T) {
convey.Convey("DMMaskCache", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oid = int64(0)
plat = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.DMMaskCache(c, tp, oid, plat)
})
})
}
func TestDaoAddMaskCache(t *testing.T) {
convey.Convey("AddMaskCache", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
mask = &model.Mask{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.AddMaskCache(c, tp, mask)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,77 @@
package dao
import (
"context"
"fmt"
"go-common/app/interface/main/dm2/model"
"go-common/library/cache/memcache"
"go-common/library/log"
)
const (
_waveFormFmt = "wf_%d_%d"
)
func (d *Dao) waveFormKey(oid int64, tp int32) string {
return fmt.Sprintf(_waveFormFmt, oid, tp)
}
// SetWaveFormCache .
func (d *Dao) SetWaveFormCache(c context.Context, waveForm *model.WaveForm) (err error) {
var (
key = d.waveFormKey(waveForm.Oid, waveForm.Type)
conn = d.subtitleMc.Get(c)
item *memcache.Item
)
defer conn.Close()
item = &memcache.Item{
Key: key,
Object: waveForm,
Flags: memcache.FlagJSON | memcache.FlagGzip,
Expiration: d.subtitleMcExpire,
}
if err = conn.Set(item); err != nil {
log.Error("conn.Set(%v) error(%v)", item, err)
}
return
}
// WaveFormCache .
func (d *Dao) WaveFormCache(c context.Context, oid int64, tp int32) (waveForm *model.WaveForm, err error) {
var (
item *memcache.Item
conn = d.subtitleMc.Get(c)
key = d.waveFormKey(oid, tp)
)
defer conn.Close()
if item, err = conn.Get(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
} else {
log.Error("memcache.Get(%s) error(%v)", key, err)
}
return
}
if err = conn.Scan(item, &waveForm); err != nil {
log.Error("mc.Scan() error(%v)", err)
}
return
}
// DelWaveFormCache .
func (d *Dao) DelWaveFormCache(c context.Context, oid int64, tp int32) (err error) {
var (
key = d.waveFormKey(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
}

View File

@@ -0,0 +1,72 @@
package dao
import (
"context"
"go-common/app/interface/main/dm2/model"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaowaveFormKey(t *testing.T) {
convey.Convey("waveFormKey", t, func(ctx convey.C) {
var (
oid = int64(0)
tp = int32(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := testDao.waveFormKey(oid, tp)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoSetWaveFormCache(t *testing.T) {
convey.Convey("SetWaveFormCache", t, func(ctx convey.C) {
var (
c = context.Background()
waveForm = &model.WaveForm{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.SetWaveFormCache(c, waveForm)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoWaveFormCache(t *testing.T) {
convey.Convey("WaveFormCache", 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) {
waveForm, err := testDao.WaveFormCache(c, oid, tp)
ctx.Convey("Then err should be nil.waveForm should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(waveForm, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoDelWaveFormCache(t *testing.T) {
convey.Convey("DelWaveFormCache", 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) {
err := testDao.DelWaveFormCache(c, oid, tp)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,482 @@
package dao
import (
"context"
"errors"
"fmt"
"sync"
"go-common/app/interface/main/dm2/model"
"go-common/library/database/sql"
"go-common/library/log"
"go-common/library/sync/errgroup"
"go-common/library/time"
"go-common/library/xstr"
)
const (
_pageSize = 1000
_subjectSharding = 100
_indexSharding = 1000
_contentSharding = 1000
_subSQL = "SELECT id,type,oid,pid,mid,state,attr,acount,count,mcount,move_count,maxlimit,childpool,ctime,mtime FROM dm_subject_%02d WHERE type=? AND oid=?"
_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)"
_updateSubAttr = "UPDATE dm_subject_%02d SET attr=? WHERE type=? AND oid=?"
_idxByidSQL = "SELECT id,type,oid,mid,progress,state,pool,attr,ctime,mtime FROM dm_index_%03d WHERE type=? AND id=?"
_idxsByidSQL = "SELECT id,type,oid,mid,progress,state,pool,attr,ctime,mtime FROM dm_index_%03d WHERE type=? AND id IN(%s)"
_getIndexSQL = "SELECT id,type,oid,mid,progress,state,pool,attr,ctime,mtime FROM dm_index_%03d WHERE type=? AND oid=? AND state IN(0,6)"
_getContentSQL = "SELECT dmid,fontsize,color,mode,ip,plat,msg,ctime,mtime FROM dm_content_%03d WHERE dmid=?"
_contentsSQL = "SELECT dmid,fontsize,color,mode,ip,plat,msg,ctime,mtime FROM dm_content_%03d WHERE dmid IN(%s)"
_contentsSpeSQL = "SELECT dmid,msg,ctime,mtime FROM dm_special_content WHERE dmid IN(%s)"
_idxSegIDSQL = "SELECT id FROM dm_index_%03d WHERE type=? AND oid=? AND progress>=? AND progress<? AND state IN(0,6) AND pool = ? limit ?"
_selectDMCount = "SELECT count(*) from dm_index_%03d WHERE type=? AND oid=? AND state IN(%s)"
_updateIdxStatSQL = "UPDATE dm_index_%03d SET state=? WHERE type=? AND oid=? AND id IN(%s)"
_updateUserIdxStatSQL = "UPDATE dm_index_%03d SET state=? WHERE type=? AND oid=? AND id IN(%s) and mid=?"
_updateIdxPoolSQL = "UPDATE dm_index_%03d SET pool=? WHERE type=? AND oid=? AND id IN(%s)"
_updateIdxAttrSQL = "UPDATE dm_index_%03d SET attr=? WHERE id=?"
_judgeIdxPageSQL = "SELECT id,type,oid,mid,progress,state,pool,attr,ctime,mtime FROM dm_index_%03d WHERE type=? AND oid=? AND ctime >=? AND ctime <=? AND progress>=? AND progress<=? AND state IN (0,1,2,6,8,9,10,11) limit 1000"
_updateSubPoolSQL = "UPDATE dm_subject_%02d SET childpool=? WHERE type=? AND oid=?"
_incrSubMoveCntSQL = "UPDATE dm_subject_%02d SET move_count=move_count+? WHERE type=? AND oid=?"
_updateSubMCountSQL = "UPDATE dm_subject_%02d SET mcount=? WHERE type=? AND oid=?"
_incrSubCountSQL = "UPDATE dm_subject_%02d SET count=count+? WHERE type=? AND oid=?"
_getSpecialLocation = "SELECT id,type,oid,locations FROM dm_special_content_location WHERE oid=? AND type=?"
_getSpecialIdxSQL = "SELECT id,type,oid,mid,progress,state,pool,attr,ctime,mtime FROM dm_index_%03d WHERE oid=? AND type=? AND state IN(0,6) AND pool=2"
// upper config
_addUpperCfgSQL = "REPLACE INTO dm_upper_config(mid,advance_permit) VALUES(?,?)"
_selUpperCfgSQL = "SELECT advance_permit FROM dm_upper_config WHERE mid=?"
)
// 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.dmReader.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.dmReader.Query(errCtx, fmt.Sprintf(_getSubjectsSQL, k, xstr.JoinInts(v)), tp)
if err != nil {
log.Error("dmReader.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()
}
err = rows.Err()
return
})
}
if err = wg.Wait(); err != nil {
log.Error("d.Subjects() error(%v)", err)
return
}
if len(res) == 0 {
res = nil
}
return
}
// UptSubAttr update subject attr
func (d *Dao) UptSubAttr(c context.Context, tp int32, oid int64, attr int32) (affect int64, err error) {
res, err := d.dmWriter.Exec(c, fmt.Sprintf(_updateSubAttr, d.hitSubject(oid)), attr, tp, oid)
if err != nil {
log.Error("dmWriter.Exec(%s,%d,%d,%d) error(%v)", _updateSubAttr, attr, 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.dmWriter.Exec(c, fmt.Sprintf(_incrSubMoveCntSQL, d.hitSubject(oid)), count, tp, oid)
if err != nil {
log.Error("d.dmWriter.Exec(%s,%d,%d,%d) error(%v)", _incrSubMoveCntSQL, tp, oid, count, 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.dmWriter.Exec(c, fmt.Sprintf(_updateSubMCountSQL, d.hitSubject(oid)), cnt, tp, oid)
if err != nil {
log.Error("d.dmWriter.Exect(%s,%d,%d,%d) error(%v)", _updateSubMCountSQL, cnt, tp, oid, 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.dmWriter.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()
}
// IncrSubjectCount update count.
func (d *Dao) IncrSubjectCount(c context.Context, tp int32, oid, count int64) (affect int64, err error) {
res, err := d.dmWriter.Exec(c, fmt.Sprintf(_incrSubCountSQL, d.hitSubject(oid)), count, tp, oid)
if err != nil {
log.Error("dmWriter.Exec() error(%v)", err)
return
}
return res.RowsAffected()
}
// DMIDs normal dm ids
func (d *Dao) DMIDs(c context.Context, tp int32, oid, ps, pe, limit int64, pool int32) (dmids []int64, err error) {
rows, err := d.dmReader.Query(c, fmt.Sprintf(_idxSegIDSQL, d.hitIndex(oid)), tp, oid, ps, pe, pool, limit)
if err != nil {
log.Error("db.Query() error(%v)", err)
return
}
defer rows.Close()
var dmid int64
for rows.Next() {
if err = rows.Scan(&dmid); err != nil {
log.Error("rows.Scan() error(%v)", err)
return
}
dmids = append(dmids, dmid)
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}
// Indexs get dm index by oid.
func (d *Dao) Indexs(c context.Context, tp int32, oid int64) (idxMap map[int64]*model.DM, dmids, special []int64, err error) {
rows, err := d.dmReader.Query(c, fmt.Sprintf(_getIndexSQL, d.hitIndex(oid)), tp, oid)
if err != nil {
log.Error("dmReader.Query() error(%v)", err)
return
}
defer rows.Close()
idxMap = make(map[int64]*model.DM)
for rows.Next() {
idx := &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
dmids = append(dmids, idx.ID)
if idx.Pool == model.PoolSpecial {
special = append(special, idx.ID)
}
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}
// IndexByid get index by dmid.
func (d *Dao) IndexByid(c context.Context, tp int8, oid, dmid int64) (idx *model.DM, err error) {
row := d.dmReader.QueryRow(c, fmt.Sprintf(_idxByidSQL, d.hitIndex(oid)), tp, dmid)
idx = &model.DM{}
err = row.Scan(&idx.ID, &idx.Type, &idx.Oid, &idx.Mid, &idx.Progress, &idx.State, &idx.Pool, &idx.Attr, &idx.Ctime, &idx.Mtime)
if err != nil {
if err == sql.ErrNoRows {
idx = nil
err = nil
} else {
log.Error("row.Scan() error(%v)", err)
}
}
return
}
// IndexsByid get dm index by dmids.
func (d *Dao) IndexsByid(c context.Context, tp int32, oid int64, dmids []int64) (idxMap map[int64]*model.DM, special []int64, err error) {
query := fmt.Sprintf(_idxsByidSQL, d.hitIndex(oid), xstr.JoinInts(dmids))
rows, err := d.dmReader.Query(c, query, tp)
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 := &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)
}
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}
// JudgeIndex get judget index.
func (d *Dao) JudgeIndex(c context.Context, tp int8, oid int64, ctime1, ctime2 time.Time, prog1, prog2 int32) (idxs []*model.DM, special []int64, err error) {
query := fmt.Sprintf(_judgeIdxPageSQL, d.hitIndex(oid))
rows, err := d.dmReader.Query(c, query, tp, oid, ctime1, ctime2, prog1, prog2)
if err != nil {
log.Error("db.Query() error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
idx := &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
}
idxs = append(idxs, idx)
if idx.Pool == model.PoolSpecial {
special = append(special, idx.ID)
}
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}
// Content dm content by dmid
func (d *Dao) Content(c context.Context, oid, dmid int64) (ct *model.Content, err error) {
ct = &model.Content{}
row := d.dmReader.QueryRow(c, fmt.Sprintf(_getContentSQL, d.hitContent(oid)), dmid)
if err = row.Scan(&ct.ID, &ct.FontSize, &ct.Color, &ct.Mode, &ct.IP, &ct.Plat, &ct.Msg, &ct.Ctime, &ct.Mtime); err != nil {
ct = nil
log.Error("row.Scan() error(%v)", err)
}
return
}
// Contents multi get dm content by dmids.
func (d *Dao) Contents(c context.Context, oid int64, dmids []int64) (ctsMap map[int64]*model.Content, err error) {
var (
wg errgroup.Group
lock sync.Mutex
)
ctsMap = make(map[int64]*model.Content)
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.dmReader.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()
ctsMap[ct.ID] = ct
lock.Unlock()
}
err = rows.Err()
return
})
}
if err = wg.Wait(); err != nil {
log.Error("wg.Wait() error(%v)", err)
}
return
}
// ContentsSpecial multi get special dm content by dmids.
func (d *Dao) ContentsSpecial(c context.Context, dmids []int64) (res map[int64]*model.ContentSpecial, err error) {
res = make(map[int64]*model.ContentSpecial, len(dmids))
rows, err := d.dmReader.Query(c, fmt.Sprintf(_contentsSpeSQL, xstr.JoinInts(dmids)))
if err != nil {
log.Error("db.Query() error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
content := &model.ContentSpecial{}
if err = rows.Scan(&content.ID, &content.Msg, &content.Ctime, &content.Mtime); err != nil {
log.Error("rows.Scan() error(%v)", err)
return
}
res[content.ID] = content
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}
// UpdateDMStat edit dm state
func (d *Dao) UpdateDMStat(c context.Context, tp int32, oid int64, state int32, dmids []int64) (affect int64, err error) {
res, err := d.dmWriter.Exec(c, fmt.Sprintf(_updateIdxStatSQL, d.hitIndex(oid), xstr.JoinInts(dmids)), state, tp, oid)
if err != nil {
log.Error("dmWriter.Exec(%s %d) error(%v)", _updateIdxStatSQL, oid, err)
return
}
return res.RowsAffected()
}
// UpdateUserDMStat edit user dm state
func (d *Dao) UpdateUserDMStat(c context.Context, tp int32, oid, mid int64, state int32, dmids []int64) (affect int64, err error) {
if mid <= 0 || tp <= 0 || oid <= 0 || len(dmids) <= 0 {
affect = 0
err = errors.New("d.UpdateUserDMStat: invalid arguments")
return
}
res, err := d.dmWriter.Exec(c, fmt.Sprintf(_updateUserIdxStatSQL, d.hitIndex(oid), xstr.JoinInts(dmids)), state, tp, oid, mid)
if err != nil {
log.Error("dmWriter.Exec(%s %d) error(%v)", _updateIdxStatSQL, oid, err)
return
}
return res.RowsAffected()
}
// UpdateDMPool edit dm pool.
func (d *Dao) UpdateDMPool(c context.Context, tp int32, oid int64, pool int32, dmids []int64) (affect int64, err error) {
res, err := d.dmWriter.Exec(c, fmt.Sprintf(_updateIdxPoolSQL, d.hitIndex(oid), xstr.JoinInts(dmids)), pool, tp, oid)
if err != nil {
log.Error("dmWriter.Exec(%s %d) error(%v)", _updateIdxPoolSQL, oid, err)
return
}
return res.RowsAffected()
}
// UpdateDMAttr update dm attr
func (d *Dao) UpdateDMAttr(c context.Context, tp int32, oid, dmid int64, attr int32) (affect int64, err error) {
res, err := d.dmWriter.Exec(c, fmt.Sprintf(_updateIdxAttrSQL, d.hitIndex(oid)), attr, dmid)
if err != nil {
log.Error("dmWriter.Exec(%s oid:%d dmid:%d attr:%d) error(%v)", _updateIdxAttrSQL, oid, dmid, attr, err)
return
}
return res.RowsAffected()
}
// DMCount statistics dm count by dm state.
func (d *Dao) DMCount(c context.Context, typ int32, oid int64, states []int64) (count int64, err error) {
row := d.dmReader.QueryRow(c, fmt.Sprintf(_selectDMCount, d.hitIndex(oid), xstr.JoinInts(states)), typ, oid)
if err = row.Scan(&count); err != nil {
log.Error("row.Scan() error(%v)", err)
}
return
}
// SpecialDmLocation get special dm localtion url
func (d *Dao) SpecialDmLocation(c context.Context, tp int32, oid int64) (ds *model.DmSpecial, err error) {
row := d.dmReader.QueryRow(c, _getSpecialLocation, oid, tp)
ds = &model.DmSpecial{}
if err = row.Scan(&ds.ID, &ds.Type, &ds.Oid, &ds.Locations); err != nil {
if err == sql.ErrNoRows {
err = nil
ds = nil
} else {
log.Error("SpecialDmLocation.Query(tp:%v,oid:%v) error(%v)", tp, oid, err)
}
}
return
}
// SpecalDMs .
func (d *Dao) SpecalDMs(c context.Context, tp int32, oid int64) (dms map[int64]*model.DM, dmids []int64, err error) {
rows, err := d.dmReader.Query(c, fmt.Sprintf(_getSpecialIdxSQL, d.hitIndex(oid)), oid, tp)
if err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("SpecalDMs.Query(tp:%v,oid:%v) error(%v)", tp, oid, err)
}
return
}
defer rows.Close()
dms = make(map[int64]*model.DM)
for rows.Next() {
dm := &model.DM{}
if err = rows.Scan(&dm.ID, &dm.Type, &dm.Oid, &dm.Mid, &dm.Progress, &dm.State, &dm.Pool, &dm.Attr, &dm.Ctime, &dm.Mtime); err != nil {
log.Error("row.Scan() error(%v)", err)
return
}
dms[dm.ID] = dm
dmids = append(dmids, dm.ID)
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}
// AddUpperConfig add upper config.
func (d *Dao) AddUpperConfig(c context.Context, mid int64, advPermit int8) (affect int64, err error) {
res, err := d.dbDM.Exec(c, _addUpperCfgSQL, mid, advPermit)
if err != nil {
log.Error("dbDM.Exec(%s,%d,%d) error(%v)", _addUpperCfgSQL, mid, advPermit, err)
return
}
affect, err = res.RowsAffected()
return
}
// UpperConfig get upper config.
func (d *Dao) UpperConfig(c context.Context, mid int64) (advPermit int8, err error) {
row := d.dbDM.QueryRow(c, _selUpperCfgSQL, mid)
if err = row.Scan(&advPermit); err != nil {
if err == sql.ErrNoRows {
advPermit = model.AdvPermitAll
err = nil
} else {
log.Error("row.Scan() error(%v)", err)
}
}
return
}

View File

@@ -0,0 +1,117 @@
package dao
import (
"context"
"time"
"go-common/app/interface/main/dm2/model"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
// advance comment
_addAdvSQL = "INSERT INTO dm_advancecomment (dm_inid,owner,mid,type,timestamp,mode,refund) VALUES (?,?,?,?,?,?,?)"
_selAdvSQL = "SELECT buy_id,owner,dm_inid,type,mode,mid,timestamp,refund FROM dm_advancecomment WHERE owner=? AND buy_id=?"
_selAdvsSQL = "SELECT buy_id,owner,dm_inid,type,mode,mid,timestamp,refund FROM dm_advancecomment WHERE owner=? ORDER BY buy_id DESC limit 100"
_selAdvModeSQL = "SELECT type FROM dm_advancecomment WHERE dm_inid=? AND mid=? AND mode=?"
_upAdvTypeSQL = "UPDATE dm_advancecomment SET type=? WHERE buy_id=?"
_delAdvSQL = "DELETE FROM dm_advancecomment WHERE buy_id=?"
_selAdvanceCmt = "SELECT buy_id,owner,dm_inid,type,mode,mid,timestamp,refund FROM dm_advancecomment WHERE dm_inid=? AND mid=? AND mode=?"
)
// AdvanceType get advance type by cid,mid and mode.
func (d *Dao) AdvanceType(c context.Context, cid int64, mid int64, mode string) (typ string, err error) {
row := d.dbDM.QueryRow(c, _selAdvModeSQL, cid, mid, mode)
if err = row.Scan(&typ); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// Advance 获取购买高级弹幕功能状态
func (d *Dao) Advance(c context.Context, mid, id int64) (adv *model.Advance, err error) {
row := d.dbDM.QueryRow(c, _selAdvSQL, mid, id)
adv = &model.Advance{}
if err = row.Scan(&adv.ID, &adv.Owner, &adv.Cid, &adv.Type, &adv.Mode, &adv.Mid, &adv.Timestamp, &adv.Refund); err != nil {
if err == sql.ErrNoRows {
err = nil
adv = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// Advances 获取高级弹幕申请列表
func (d *Dao) Advances(c context.Context, owner int64) (res []*model.Advance, err error) {
rows, err := d.dbDM.Query(c, _selAdvsSQL, owner)
if err != nil {
log.Error("d.dbDM.Query(%s,%d) error(%v)", _selAdvsSQL, owner, err)
return
}
defer rows.Close()
for rows.Next() {
adv := &model.Advance{}
if err = rows.Scan(&adv.ID, &adv.Owner, &adv.Cid, &adv.Type, &adv.Mode, &adv.Mid, &adv.Timestamp, &adv.Refund); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
res = append(res, adv)
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}
// BuyAdvance 购买高级弹幕功能
func (d *Dao) BuyAdvance(c context.Context, mid, cid, owner, refund int64, typ, mode string) (id int64, err error) {
now := time.Now().Unix()
res, err := d.dbDM.Exec(c, _addAdvSQL, cid, owner, mid, typ, now, mode, refund)
if err != nil {
log.Error("d.dbDM.Exec(cid:%d,mid:%d,type:%s) error(%v)", cid, mid, typ, err)
return
}
return res.LastInsertId()
}
// UpdateAdvType 更新购买高级弹幕类型
func (d *Dao) UpdateAdvType(c context.Context, id int64, typ string) (affect int64, err error) {
res, err := d.dbDM.Exec(c, _upAdvTypeSQL, typ, id)
if err != nil {
log.Error("d.dbDM.Exec(%s,%s,%d) error(%v)", _upAdvTypeSQL, typ, id, err)
return
}
return res.RowsAffected()
}
// DelAdvance 删除购买高级弹幕记录
func (d *Dao) DelAdvance(c context.Context, id int64) (affect int64, err error) {
res, err := d.dbDM.Exec(c, _delAdvSQL, id)
if err != nil {
log.Error("d.dbDM.Exec(%s,%d) error(%v)", _delAdvSQL, id, err)
return
}
return res.RowsAffected()
}
// AdvanceCmt get advance comment.
func (d *Dao) AdvanceCmt(c context.Context, oid, mid int64, mode string) (adv *model.AdvanceCmt, err error) {
adv = &model.AdvanceCmt{}
row := d.dbDM.QueryRow(c, _selAdvanceCmt, oid, mid, mode)
if err = row.Scan(&adv.ID, &adv.Owner, &adv.Oid, &adv.Type, &adv.Mode, &adv.Mid, &adv.Timestamp, &adv.Refund); err != nil {
if err == sql.ErrNoRows {
adv = nil
err = nil
} else {
log.Error("row.Scan() error(%v)", err)
}
}
return
}

View File

@@ -0,0 +1,127 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoAdvanceType(t *testing.T) {
convey.Convey("AdvanceType", t, func(ctx convey.C) {
var (
c = context.Background()
cid = int64(0)
mid = int64(0)
mode = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
typ, err := testDao.AdvanceType(c, cid, mid, mode)
ctx.Convey("Then err should be nil.typ should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(typ, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoAdvance(t *testing.T) {
convey.Convey("Advance", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
id = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.Advance(c, mid, id)
})
})
}
func TestDaoAdvances(t *testing.T) {
convey.Convey("Advances", t, func(ctx convey.C) {
var (
c = context.Background()
owner = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := testDao.Advances(c, owner)
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)
})
})
})
}
func TestDaoBuyAdvance(t *testing.T) {
convey.Convey("BuyAdvance", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
cid = int64(0)
owner = int64(0)
refund = int64(0)
typ = ""
mode = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
id, err := testDao.BuyAdvance(c, mid, cid, owner, refund, typ, mode)
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)
})
})
})
}
func TestDaoUpdateAdvType(t *testing.T) {
convey.Convey("UpdateAdvType", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(0)
typ = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
affect, err := testDao.UpdateAdvType(c, id, typ)
ctx.Convey("Then err should be nil.affect should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affect, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoDelAdvance(t *testing.T) {
convey.Convey("DelAdvance", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
affect, err := testDao.DelAdvance(c, id)
ctx.Convey("Then err should be nil.affect should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affect, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoAdvanceCmt(t *testing.T) {
convey.Convey("AdvanceCmt", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
mid = int64(0)
mode = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
adv, err := testDao.AdvanceCmt(c, oid, mid, mode)
ctx.Convey("Then err should be nil.adv should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(adv, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,357 @@
package dao
import (
"bytes"
"context"
"fmt"
"strings"
"go-common/app/interface/main/dm2/model"
"go-common/library/database/sql"
"go-common/library/log"
"go-common/library/xstr"
)
const (
_upFilterSharding = 10
_userFilterSharding = 50
_userFltCntSharding = 10
_addUserFilterSQL = "INSERT INTO dm_filter_user_%02d(mid,type,filter,comment) VALUES(?,?,?,?)"
_getUserFilterSQL = "SELECT id,mid,type,filter,comment,ctime,mtime FROM dm_filter_user_%02d WHERE mid=? AND type=?"
_getUserFiltersSQL = "SELECT id,mid,type,filter,comment,ctime,mtime FROM dm_filter_user_%02d WHERE mid=?"
_getUserFiltersByIDSQL = "SELECT id,mid,type,filter,comment,ctime,mtime FROM dm_filter_user_%02d WHERE mid=? AND id IN(%s)"
_delUserFilterSQL = "DELETE FROM dm_filter_user_%02d WHERE mid=%d AND id IN(%s)"
_maddUpFilterSQL = "INSERT INTO dm_filter_up_%02d(mid,type,filter,active,comment) VALUES %s"
_getUpFilterSQL = "SELECT id,mid,type,filter,active,comment,ctime,mtime FROM dm_filter_up_%02d WHERE mid=? AND oid=0 AND type=? AND active=1"
_getUpFiltersSQL = "SELECT id,mid,type,filter,active,comment,ctime,mtime FROM dm_filter_up_%02d WHERE mid=? AND oid=0 AND active=1"
_uptUpFilterSQL = "UPDATE dm_filter_up_%02d SET active=? WHERE type=? AND mid=? AND filter IN(%s)"
_getGlbFilterSQL = "SELECT id,type,filter,ctime,mtime FROM dm_filter_global WHERE type=? AND filter=?"
_getGlbFiltersSQL = "SELECT id,type,filter,ctime,mtime FROM dm_filter_global WHERE id>=? ORDER BY id DESC LIMIT ?"
_addGlbFilterSQL = "INSERT INTO dm_filter_global(type,filter) VALUES(?,?)"
_delGlbFilterSQL = "DELETE FROM dm_filter_global WHERE id IN(%s)"
_getUserFilterCntSQL = "SELECT count FROM dm_filter_user_count_%02d WHERE mid=? AND type=?"
_getUpFilterCntSQL = "SELECT count FROM dm_filter_up_count WHERE mid=? AND type=?"
_addUserFilterCntSQL = "INSERT INTO dm_filter_user_count_%02d(mid,type,count) VALUES(?,?,?)"
_updateUserFilterCntSQL = "UPDATE dm_filter_user_count_%02d SET count=count+? WHERE mid=? AND type=? AND count<?"
_addUpFilterCntSQL = "INSERT INTO dm_filter_up_count(mid,type,count) VALUES(?,?,?)"
_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
}
func (d *Dao) hitUserFilter(mid int64) int64 {
return mid % _userFilterSharding
}
func (d *Dao) hitUserFilterCnt(mid int64) int64 {
return mid % _userFltCntSharding
}
// addslashes 函数返回在预定义字符之前添加反斜杠的字符串。
// 预定义字符是:单引号(')或反斜杠(\
func addSlashes(str string) string {
var buf bytes.Buffer
for i := 0; i < len(str); i++ {
if str[i] == '\'' || str[i] == '\\' {
buf.WriteByte('\\')
}
buf.WriteByte(str[i])
}
return buf.String()
}
// AddUserFilter add filter rule
func (d *Dao) AddUserFilter(tx *sql.Tx, mid int64, fType int8, filter, comment string) (lastID int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_addUserFilterSQL, d.hitUserFilter(mid)), mid, fType, filter, comment)
if err != nil {
log.Error("d.AddUserFilter(%d,%d,%s) error(%v)", mid, fType, filter, err)
return
}
return res.LastInsertId()
}
// UserFilter select user filter by mid and type.
func (d *Dao) UserFilter(c context.Context, mid int64, fType int8) (res []*model.UserFilter, err error) {
rows, err := d.dbDM.Query(c, fmt.Sprintf(_getUserFilterSQL, d.hitUserFilter(mid)), mid, fType)
if err != nil {
log.Error("dbDM.Query(mid:%d,type:%d) error(%v)", mid, fType, err)
return
}
defer rows.Close()
for rows.Next() {
f := &model.UserFilter{}
if err = rows.Scan(&f.ID, &f.Mid, &f.Type, &f.Filter, &f.Comment, &f.Ctime, &f.Mtime); err != nil {
log.Error("rows.Scan() error(%v)", err)
return
}
res = append(res, f)
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}
// UserFilters return all filter.
func (d *Dao) UserFilters(c context.Context, mid int64) (res []*model.UserFilter, err error) {
rows, err := d.dbDM.Query(c, fmt.Sprintf(_getUserFiltersSQL, d.hitUserFilter(mid)), mid)
if err != nil {
log.Error("dbDM.Query(mid:%d) error(%v)", mid, err)
return
}
defer rows.Close()
for rows.Next() {
f := &model.UserFilter{}
if err = rows.Scan(&f.ID, &f.Mid, &f.Type, &f.Filter, &f.Comment, &f.Ctime, &f.Mtime); err != nil {
log.Error("rows.Scan() error(%v)", err)
return
}
res = append(res, f)
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}
// UserFiltersByID return all filters specified by ids
func (d *Dao) UserFiltersByID(c context.Context, mid int64, ids []int64) (res []*model.UserFilter, err error) {
rows, err := d.dbDM.Query(c, fmt.Sprintf(_getUserFiltersByIDSQL, d.hitUserFilter(mid), xstr.JoinInts(ids)), mid)
if err != nil {
log.Error("dbDM.Quer(mid:%d, ids:%v) error(%v)", mid, ids, err)
return
}
defer rows.Close()
for rows.Next() {
f := &model.UserFilter{}
if err = rows.Scan(&f.ID, &f.Mid, &f.Type, &f.Filter, &f.Comment, &f.Ctime, &f.Mtime); err != nil {
log.Error("rows.Scan() error(%v)", err)
return
}
res = append(res, f)
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}
// DelUserFilter batch delete filter rules by mid
func (d *Dao) DelUserFilter(tx *sql.Tx, mid int64, ids []int64) (affect int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_delUserFilterSQL, d.hitUserFilter(mid), mid, xstr.JoinInts(ids)))
if err != nil {
log.Error("tx.Exec(mid:%d, ids:%v) error(%v)", mid, ids, err)
return
}
return res.RowsAffected()
}
// MultiAddUpFilter add filter rule,the key of fltMap is filter content,value is comment.
// TODO add comment field in table:dm_filter_up_xx and insert comment
func (d *Dao) MultiAddUpFilter(tx *sql.Tx, mid int64, fType int8, fltMap map[string]string) (affect int64, err error) {
var buf bytes.Buffer
for filter, comment := range fltMap {
buf.WriteString(fmt.Sprintf(`(%d,%d,'%s',%d,'%s'),`, mid, fType, addSlashes(filter), model.FilterActive, addSlashes(comment)))
}
buf.Truncate(buf.Len() - 1)
res, err := tx.Exec(fmt.Sprintf(_maddUpFilterSQL, d.hitUpFilter(mid), buf.String()))
if err != nil {
log.Error("d.AddUpFilter(mid:%d,type:%d,filters:%v) error(%v)", mid, fType, fltMap, err)
return
}
return res.RowsAffected()
}
// UpFilter return filter rules by mid and filter type.
func (d *Dao) UpFilter(c context.Context, mid int64, fType int8) (res []*model.UpFilter, err error) {
res = make([]*model.UpFilter, 0)
rows, err := d.dbDM.Query(c, fmt.Sprintf(_getUpFilterSQL, d.hitUpFilter(mid)), mid, fType)
if err != nil {
log.Error("dbDM.Query(mid:%d,type:%d) error(%v)", mid, fType, err)
return
}
defer rows.Close()
for rows.Next() {
f := &model.UpFilter{}
if err = rows.Scan(&f.ID, &f.Mid, &f.Type, &f.Filter, &f.Active, &f.Comment, &f.Ctime, &f.Mtime); err != nil {
log.Error("rows.Scan() error(%v)", err)
return
}
res = append(res, f)
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}
// UpFilters return all filter rules
func (d *Dao) UpFilters(c context.Context, mid int64) (res []*model.UpFilter, err error) {
rows, err := d.dbDM.Query(c, fmt.Sprintf(_getUpFiltersSQL, d.hitUpFilter(mid)), mid)
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.Mid, &f.Type, &f.Filter, &f.Active, &f.Comment, &f.Ctime, &f.Mtime); err != nil {
log.Error("rows.Scan() error(%v)", err)
return
}
res = append(res, f)
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}
// UpdateUpFilter batch edit filter.
func (d *Dao) UpdateUpFilter(tx *sql.Tx, mid int64, fType, active int8, filters []string) (affect int64, err error) {
sli := make([]string, len(filters))
for i, ss := range filters {
sli[i] = "'" + addSlashes(ss) + "'"
}
filter := strings.Join(sli, ",")
res, err := tx.Exec(fmt.Sprintf(_uptUpFilterSQL, d.hitUpFilter(mid), filter), active, fType, mid)
if err != nil {
log.Error("tx.Exec(mid:%d,filters:%v) error(%v)", mid, filters, err)
return
}
return res.RowsAffected()
}
// AddGlobalFilter add filter rule
func (d *Dao) AddGlobalFilter(c context.Context, fType int8, filter string) (lastID int64, err error) {
res, err := d.dbDM.Exec(c, _addGlbFilterSQL, fType, filter)
if err != nil {
log.Error("dbDM.Exec(%d,%s) error(%v)", fType, filter, err)
return
}
return res.LastInsertId()
}
// GlobalFilter select global filters by type and filter.
func (d *Dao) GlobalFilter(c context.Context, fType int8, filter string) (res []*model.GlobalFilter, err error) {
rows, err := d.dbDM.Query(c, _getGlbFilterSQL, fType, filter)
if err != nil {
log.Error("d.dbDM(type:%d, filter:%s) error(%v)", fType, filter, err)
return
}
defer rows.Close()
for rows.Next() {
f := &model.GlobalFilter{}
if err = rows.Scan(&f.ID, &f.Type, &f.Filter, &f.Ctime, &f.Mtime); err != nil {
log.Error("rows.Scan() error(%v)", err)
return
}
res = append(res, f)
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}
// GlobalFilters return all filter rules
func (d *Dao) GlobalFilters(c context.Context, sid, limit int64) (res []*model.GlobalFilter, err error) {
var rows *sql.Rows
if rows, err = d.dbDM.Query(c, _getGlbFiltersSQL, sid, limit); err != nil {
log.Error("dbDM.Query(start id:%d, limit:%d) error(%v)", sid, limit, err)
return
}
defer rows.Close()
for rows.Next() {
r := &model.GlobalFilter{}
if err = rows.Scan(&r.ID, &r.Type, &r.Filter, &r.Ctime, &r.Mtime); err != nil {
log.Error("rows.Scan() error(%v)", err)
return
}
res = append(res, r)
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}
// DelGlobalFilters batch delete filter rules
func (d *Dao) DelGlobalFilters(c context.Context, ids []int64) (affect int64, err error) {
res, err := d.dbDM.Exec(c, fmt.Sprintf(_delGlbFilterSQL, xstr.JoinInts(ids)))
if err != nil {
log.Error("dbDM.Exec(ids:%v) error(%v)", ids, err)
return
}
return res.RowsAffected()
}
// UserFilterCnt get count by mid and type
func (d *Dao) UserFilterCnt(c context.Context, tx *sql.Tx, mid int64, tp int8) (count int, err error) {
row := tx.QueryRow(fmt.Sprintf(_getUserFilterCntSQL, d.hitUserFilterCnt(mid)), mid, tp)
if err = row.Scan(&count); err != nil {
if err == sql.ErrNoRows {
count = model.FilterNotExist
err = nil
} else {
log.Error("rows.Scan() error(%v)", err)
}
}
return
}
// InsertUserFilterCnt add a new row
func (d *Dao) InsertUserFilterCnt(c context.Context, tx *sql.Tx, mid int64, tp int8, count int) (id int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_addUserFilterCntSQL, d.hitUserFilterCnt(mid)), mid, tp, count)
if err != nil {
log.Error("d.InsertUserFilterCnt(mid:%d, type:%d, count:%d) error(%v)", mid, tp, count, err)
return
}
return res.LastInsertId()
}
// UpdateUserFilterCnt set count
func (d *Dao) UpdateUserFilterCnt(c context.Context, tx *sql.Tx, mid int64, tp int8, count, limit int64) (affect int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_updateUserFilterCntSQL, d.hitUserFilterCnt(mid)), count, mid, tp, limit)
if err != nil {
log.Error("d.UpdateUserFilterCnt(mid:%d, type:%d, count:%d) error(%v)", mid, tp, count, err)
return
}
return res.RowsAffected()
}
// UpFilterCnt get count by mid and type
func (d *Dao) UpFilterCnt(c context.Context, tx *sql.Tx, mid int64, tp int8) (count int, err error) {
row := tx.QueryRow(_getUpFilterCntSQL, mid, tp)
if err = row.Scan(&count); err != nil {
if err == sql.ErrNoRows {
count = model.FilterNotExist
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// InsertUpFilterCnt insert up rule count.
func (d *Dao) InsertUpFilterCnt(c context.Context, tx *sql.Tx, mid int64, tp int8, count int) (id int64, err error) {
res, err := tx.Exec(_addUpFilterCntSQL, mid, tp, count)
if err != nil {
log.Error("d.InsertUpFilterCnt(mid:%d, type:%d, count:%d) error(%v)", mid, tp, count, err)
return
}
return res.LastInsertId()
}
// UpdateUpFilterCnt set count
func (d *Dao) UpdateUpFilterCnt(c context.Context, tx *sql.Tx, mid int64, tp int8, count, limit int) (affect int64, err error) {
res, err := tx.Exec(_updateUpFilterCntSQL, count, mid, tp, limit)
if err != nil {
log.Error("d.UpdateUpFilterCnt(mid:%d, type:%d, count:%d) error(%v)", mid, tp, count, err)
return
}
return res.RowsAffected()
}

View File

@@ -0,0 +1,363 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaohitUpFilter(t *testing.T) {
convey.Convey("hitUpFilter", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := testDao.hitUpFilter(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaohitUserFilter(t *testing.T) {
convey.Convey("hitUserFilter", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := testDao.hitUserFilter(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaohitUserFilterCnt(t *testing.T) {
convey.Convey("hitUserFilterCnt", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := testDao.hitUserFilterCnt(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoaddSlashes(t *testing.T) {
convey.Convey("addSlashes", t, func(ctx convey.C) {
var (
str = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := addSlashes(str)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoAddUserFilter(t *testing.T) {
convey.Convey("AddUserFilter", t, func(ctx convey.C) {
var (
tx, _ = testDao.BeginBiliDMTrans(c)
mid = int64(0)
fType = int8(0)
filter = ""
comment = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.AddUserFilter(tx, mid, fType, filter, comment)
})
ctx.Reset(func() {
tx.Commit()
})
})
}
func TestDaoUserFilter(t *testing.T) {
convey.Convey("UserFilter", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
fType = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.UserFilter(c, mid, fType)
})
})
}
func TestDaoUserFilters(t *testing.T) {
convey.Convey("UserFilters", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := testDao.UserFilters(c, mid)
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)
})
})
})
}
func TestDaoUserFiltersByID(t *testing.T) {
convey.Convey("UserFiltersByID", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
ids = []int64{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.UserFiltersByID(c, mid, ids)
})
})
}
func TestDaoDelUserFilter(t *testing.T) {
convey.Convey("DelUserFilter", t, func(ctx convey.C) {
var (
tx, _ = testDao.BeginBiliDMTrans(c)
mid = int64(0)
ids = []int64{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.DelUserFilter(tx, mid, ids)
})
ctx.Reset(func() {
tx.Commit()
})
})
}
func TestDaoMultiAddUpFilter(t *testing.T) {
convey.Convey("MultiAddUpFilter", t, func(ctx convey.C) {
var (
tx, _ = testDao.BeginBiliDMTrans(c)
mid = int64(0)
fType = int8(0)
fltMap = map[string]string{
"test": "test",
}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.MultiAddUpFilter(tx, mid, fType, fltMap)
})
ctx.Reset(func() {
tx.Commit()
})
})
}
func TestDaoUpFilter(t *testing.T) {
convey.Convey("UpFilter", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
fType = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.UpFilter(c, mid, fType)
})
})
}
func TestDaoUpFilters(t *testing.T) {
convey.Convey("UpFilters", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.UpFilters(c, mid)
})
})
}
func TestDaoUpdateUpFilter(t *testing.T) {
convey.Convey("UpdateUpFilter", t, func(ctx convey.C) {
var (
tx, _ = testDao.BeginBiliDMTrans(context.TODO())
mid = int64(0)
fType = int8(0)
active = int8(0)
filters = []string{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.UpdateUpFilter(tx, mid, fType, active, filters)
})
ctx.Reset(func() {
tx.Commit()
})
})
}
func TestDaoAddGlobalFilter(t *testing.T) {
convey.Convey("AddGlobalFilter", t, func(ctx convey.C) {
var (
c = context.Background()
fType = int8(0)
filter = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
lastID, err := testDao.AddGlobalFilter(c, fType, filter)
ctx.Convey("Then err should be nil.lastID should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(lastID, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoGlobalFilter(t *testing.T) {
convey.Convey("GlobalFilter", t, func(ctx convey.C) {
var (
c = context.Background()
fType = int8(0)
filter = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := testDao.GlobalFilter(c, fType, filter)
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)
})
})
})
}
func TestDaoGlobalFilters(t *testing.T) {
convey.Convey("GlobalFilters", t, func(ctx convey.C) {
var (
c = context.Background()
sid = int64(0)
limit = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.GlobalFilters(c, sid, limit)
})
})
}
func TestDaoDelGlobalFilters(t *testing.T) {
convey.Convey("DelGlobalFilters", t, func(ctx convey.C) {
var (
c = context.Background()
ids = []int64{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.DelGlobalFilters(c, ids)
})
})
}
func TestDaoUserFilterCnt(t *testing.T) {
convey.Convey("UserFilterCnt", t, func(ctx convey.C) {
var (
tx, _ = testDao.BeginBiliDMTrans(c)
mid = int64(0)
tp = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.UserFilterCnt(c, tx, mid, tp)
})
ctx.Reset(func() {
tx.Commit()
})
})
}
func TestDaoInsertUserFilterCnt(t *testing.T) {
convey.Convey("InsertUserFilterCnt", t, func(ctx convey.C) {
var (
tx, _ = testDao.BeginBiliDMTrans(c)
mid = int64(0)
tp = int8(0)
count = int(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.InsertUserFilterCnt(c, tx, mid, tp, count)
})
ctx.Reset(func() {
tx.Commit()
})
})
}
func TestDaoUpdateUserFilterCnt(t *testing.T) {
convey.Convey("UpdateUserFilterCnt", t, func(ctx convey.C) {
var (
tx, _ = testDao.BeginBiliDMTrans(c)
mid = int64(0)
tp = int8(0)
count = int64(0)
limit = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.UpdateUserFilterCnt(c, tx, mid, tp, count, limit)
})
ctx.Reset(func() {
tx.Commit()
})
})
}
func TestDaoUpFilterCnt(t *testing.T) {
convey.Convey("UpFilterCnt", t, func(ctx convey.C) {
var (
tx, _ = testDao.BeginBiliDMTrans(c)
mid = int64(0)
tp = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.UpFilterCnt(c, tx, mid, tp)
})
ctx.Reset(func() {
tx.Commit()
})
})
}
func TestDaoInsertUpFilterCnt(t *testing.T) {
convey.Convey("InsertUpFilterCnt", t, func(ctx convey.C) {
var (
tx, _ = testDao.BeginBiliDMTrans(c)
mid = int64(0)
tp = int8(0)
count = int(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.InsertUpFilterCnt(c, tx, mid, tp, count)
})
ctx.Reset(func() {
tx.Commit()
})
})
}
func TestDaoUpdateUpFilterCnt(t *testing.T) {
convey.Convey("UpdateUpFilterCnt", t, func(ctx convey.C) {
var (
tx, _ = testDao.BeginBiliDMTrans(c)
mid = int64(0)
tp = int8(0)
count = int(0)
limit = int(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.UpdateUpFilterCnt(c, tx, mid, tp, count, limit)
})
ctx.Reset(func() {
tx.Commit()
})
})
}

View File

@@ -0,0 +1,269 @@
package dao
import (
"context"
"database/sql"
"fmt"
"time"
"go-common/app/interface/main/dm2/model"
xsql "go-common/library/database/sql"
"go-common/library/log"
"go-common/library/xstr"
)
const (
_subtitleSharding = 100
_getSubtitlePubIds = "SELECT subtitle_id FROM subtitle_pub WHERE oid=? AND type=? AND is_delete=0"
_addSubtitlePub = "INSERT INTO subtitle_pub(oid,type,lan,subtitle_id,is_delete) VALUES(?,?,?,?,?) ON DUPLICATE KEY UPDATE subtitle_id=?,is_delete=?"
_addSubtitleSubject = "INSERT INTO subtitle_subject(aid,allow,lan_code) VALUES(?,?,?) ON DUPLICATE KEY UPDATE allow=?,lan_code=?"
_getSubtitleSubject = "SELECT aid,allow,attr,lan_code from subtitle_subject WHERE aid=?"
_getSubtitleOne = "SELECT id,oid,type,lan,aid,mid,author_mid,up_mid,is_sign,is_lock,status,checksum,subtitle_url,pub_time,reject_comment FROM subtitle_%02d WHERE oid=? AND type=? AND lan=? AND status=5 ORDER BY pub_time DESC limit 1"
_getSubtitles = "SELECT id,oid,type,lan,aid,mid,author_mid,up_mid,is_sign,is_lock,status,checksum,subtitle_url,pub_time,reject_comment,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,checksum,subtitle_url,pub_time,reject_comment,mtime FROM subtitle_%02d WHERE id = ? AND status!=4"
_getSubtitleDraft = "SELECT id,oid,type,lan,aid,mid,author_mid,up_mid,is_sign,is_lock,status,checksum,subtitle_url,pub_time,reject_comment FROM subtitle_%02d WHERE oid=? AND type=? AND lan=? AND mid=? AND pub_time=0"
_updateSubtitle = "UPDATE subtitle_%02d SET aid=?,author_mid=?,up_mid=?,is_sign=?,is_lock=?,status=?,checksum=?,subtitle_url=?,pub_time=?,reject_comment=? WHERE id=?"
_addSubtitle = "INSERT INTO subtitle_%02d(id,oid,type,lan,aid,mid,author_mid,up_mid,is_sign,is_lock,status,checksum,subtitle_url,pub_time,reject_comment) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
_addWaveForm = "INSERT INTO subtitle_waveform(oid,type,state,wave_form_url) VALUES(?,?,?,?) ON DUPLICATE KEY UPDATE state=?,wave_form_url=?"
_getWaveForm = "SELECT oid,type,state,wave_form_url,mtime FROM subtitle_waveform WHERE oid=? AND type=?"
_getSubtitleLans = "SELECT code,lan,doc_zh FROM subtitle_language WHERE is_delete=0"
_addSubtitleLan = "INSERT INTO subtitle_language(code,lan,doc_zh,doc_en,is_delete) VALUES(?,?,?,?,?) ON DUPLICATE KEY UPDATE lan=?,doc_zh=?,doc_en=?,is_delete=?"
)
func (d *Dao) hitSubtitle(oid int64) int64 {
return oid % _subtitleSharding
}
// AddSubtitleSubject .
func (d *Dao) AddSubtitleSubject(c context.Context, subtitleSubject *model.SubtitleSubject) (err error) {
if _, err = d.dbDM.Exec(c, _addSubtitleSubject, subtitleSubject.Aid, subtitleSubject.Allow, subtitleSubject.Lan, subtitleSubject.Allow, 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.dbDM.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
}
// GetSubtitleIds .
func (d *Dao) GetSubtitleIds(c context.Context, oid int64, tp int32) (subtitlIds []int64, err error) {
rows, err := d.dbDM.Query(c, _getSubtitlePubIds, oid, tp)
if err != nil {
log.Error("params(oid:%v,tp:%v),error(%v)", oid, tp, err)
return
}
defer rows.Close()
for rows.Next() {
var subtitleID int64
if err = rows.Scan(&subtitleID); err != nil {
log.Error("params(oid:%v,tp:%v),=error(%v)", oid, tp, err)
return
}
subtitlIds = append(subtitlIds, subtitleID)
}
if err = rows.Err(); err != nil {
log.Error("params(oid:%v,tp:%v),=error(%v)", oid, tp, err)
return
}
return
}
// GetSubtitles .
func (d *Dao) GetSubtitles(c context.Context, oid int64, subtitleIds []int64) (subtitles []*model.Subtitle, err error) {
rows, err := d.dbDM.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.CheckSum, &subtitle.SubtitleURL, &subtitle.PubTime, &subtitle.RejectComment, &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
}
// GetSubtitleDraft query a SubtitleDrfat
func (d *Dao) GetSubtitleDraft(c context.Context, oid int64, tp int32, mid int64, lan uint8) (subtitle *model.Subtitle, err error) {
subtitle = &model.Subtitle{}
row := d.dbDM.QueryRow(c, fmt.Sprintf(_getSubtitleDraft, d.hitSubtitle(oid)), oid, tp, lan, mid)
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.CheckSum, &subtitle.SubtitleURL, &subtitle.PubTime, &subtitle.RejectComment); err != nil {
if err == sql.ErrNoRows {
err = nil
subtitle = nil
return
}
log.Error("params(oid:%v, tp:%v, mid:%v, lan:%v),=error(%v)", oid, tp, mid, lan, err)
return
}
return
}
// GetSubtitle query a SubtitleDrfat
func (d *Dao) GetSubtitle(c context.Context, oid int64, subtitleID int64) (subtitle *model.Subtitle, err error) {
var t time.Time
subtitle = &model.Subtitle{}
row := d.dbDM.QueryRow(c, fmt.Sprintf(_getSubtitle, d.hitSubtitle(oid)), subtitleID)
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.CheckSum, &subtitle.SubtitleURL, &subtitle.PubTime, &subtitle.RejectComment, &t); err != nil {
if err == sql.ErrNoRows {
err = nil
subtitle = nil
return
}
log.Error("params(subtitleID:%v),error(%v)", subtitleID, err)
return
}
subtitle.Mtime = t.Unix()
return
}
// AddSubtitle .
func (d *Dao) AddSubtitle(c context.Context, subtitle *model.Subtitle) (insertID int64, err error) {
var res sql.Result
if res, err = d.dbDM.Exec(c, fmt.Sprintf(_addSubtitle, d.hitSubtitle(subtitle.Oid)),
subtitle.ID, subtitle.Oid, subtitle.Type, subtitle.Lan, subtitle.Aid, subtitle.Mid, subtitle.AuthorID, subtitle.UpMid, subtitle.IsSign, subtitle.IsLock, subtitle.Status,
subtitle.CheckSum, subtitle.SubtitleURL, subtitle.PubTime, subtitle.RejectComment); err != nil {
log.Error("params(%+v),error(%v)", subtitle, err)
return
}
if insertID, err = res.LastInsertId(); err != nil {
log.Error("params(%+v),error(%v)", subtitle, err)
return
}
return
}
// UpdateSubtitle .
func (d *Dao) UpdateSubtitle(c context.Context, subtitle *model.Subtitle) (err error) {
if _, err = d.dbDM.Exec(c, fmt.Sprintf(_updateSubtitle, d.hitSubtitle(subtitle.Oid)),
subtitle.Aid, subtitle.AuthorID, subtitle.UpMid, subtitle.IsSign, subtitle.IsLock, subtitle.Status, subtitle.CheckSum, subtitle.SubtitleURL, subtitle.PubTime, subtitle.RejectComment,
subtitle.ID); err != nil {
log.Error("params(%+v),error(%v)", subtitle, err)
return
}
return
}
// TxUpdateSubtitle .
func (d *Dao) TxUpdateSubtitle(tx *xsql.Tx, subtitle *model.Subtitle) (err error) {
if _, err = tx.Exec(fmt.Sprintf(_updateSubtitle, d.hitSubtitle(subtitle.Oid)),
subtitle.Aid, subtitle.AuthorID, subtitle.UpMid, subtitle.IsSign, subtitle.IsLock, subtitle.Status, subtitle.CheckSum, subtitle.SubtitleURL, subtitle.PubTime, subtitle.RejectComment,
subtitle.ID); err != nil {
log.Error("params(%+v),error(%v)", subtitle, err)
return
}
return
}
// TxAddSubtitlePub .
func (d *Dao) TxAddSubtitlePub(tx *xsql.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
}
// TxGetSubtitleOne .
func (d *Dao) TxGetSubtitleOne(tx *xsql.Tx, oid int64, tp int32, lan uint8) (subtitle *model.Subtitle, err error) {
subtitle = &model.Subtitle{}
row := tx.QueryRow(fmt.Sprintf(_getSubtitleOne, d.hitSubtitle(oid)), oid, tp, lan)
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.CheckSum, &subtitle.SubtitleURL, &subtitle.PubTime, &subtitle.RejectComment); err != nil {
if err == sql.ErrNoRows {
err = nil
subtitle = nil
return
}
log.Error("params(oid:%v, tp:%v, lan:%v),error(%v)", oid, tp, lan, err)
return
}
return
}
// SubtitleLans .
func (d *Dao) SubtitleLans(c context.Context) (subtitleLans []*model.SubtitleLan, err error) {
rows, err := d.dbDM.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
}
// SubtitleLanAdd .
func (d *Dao) SubtitleLanAdd(c context.Context, subtitleLan *model.SubtitleLan) (err error) {
if _, err = d.dbDM.Exec(c, _addSubtitleLan, subtitleLan.Code, subtitleLan.Lan, subtitleLan.DocZh, subtitleLan.DocEn, subtitleLan.IsDelete, subtitleLan.Lan, subtitleLan.DocZh, subtitleLan.DocEn, subtitleLan.IsDelete); err != nil {
log.Error("SubtitleLanAdd.params(subtitleLan:%+v),error(%v)", subtitleLan, err)
return
}
return
}
// UpsertWaveFrom .
func (d *Dao) UpsertWaveFrom(c context.Context, waveForm *model.WaveForm) (err error) {
if _, err = d.dbDM.Exec(c, _addWaveForm, waveForm.Oid, waveForm.Type, waveForm.State, waveForm.WaveFromURL, waveForm.State, waveForm.WaveFromURL); err != nil {
log.Error("params(waveForm:%+v),error(%v)", waveForm, err)
return
}
return
}
// GetWaveForm .
func (d *Dao) GetWaveForm(c context.Context, oid int64, tp int32) (waveForm *model.WaveForm, err error) {
var t time.Time
row := d.dbDM.QueryRow(c, _getWaveForm, oid, tp)
waveForm = &model.WaveForm{}
if err = row.Scan(&waveForm.Oid, &waveForm.Type, &waveForm.State, &waveForm.WaveFromURL, &t); err != nil {
if err == sql.ErrNoRows {
err = nil
waveForm = nil
return
}
log.Error("params(oid:%v, tp:%v),error(%v)", oid, tp, err)
return
}
waveForm.Mtime = t.Unix()
return
}

View File

@@ -0,0 +1,260 @@
package dao
import (
"context"
"go-common/app/interface/main/dm2/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 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)
})
})
})
}
func TestDaoGetSubtitleIds(t *testing.T) {
convey.Convey("GetSubtitleIds", 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) {
subtitlIds, err := testDao.GetSubtitleIds(c, oid, tp)
ctx.Convey("Then err should be nil.subtitlIds should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(subtitlIds, 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 TestDaoGetSubtitleDraft(t *testing.T) {
convey.Convey("GetSubtitleDraft", 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) {
subtitle, err := testDao.GetSubtitleDraft(c, oid, tp, mid, lan)
ctx.Convey("Then err should be nil.subtitle should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(subtitle, convey.ShouldNotBeNil)
})
})
})
}
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 TestDaoAddSubtitle(t *testing.T) {
convey.Convey("AddSubtitle", t, func(ctx convey.C) {
var (
c = context.Background()
subtitle = &model.Subtitle{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.AddSubtitle(c, subtitle)
})
})
}
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 TestDaoTxUpdateSubtitle(t *testing.T) {
convey.Convey("TxUpdateSubtitle", t, func(ctx convey.C) {
var (
tx, _ = testDao.BeginBiliDMTrans(c)
subtitle = &model.Subtitle{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.TxUpdateSubtitle(tx, subtitle)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
ctx.Reset(func() {
tx.Commit()
})
})
}
func TestDaoTxAddSubtitlePub(t *testing.T) {
convey.Convey("TxAddSubtitlePub", t, func(ctx convey.C) {
var (
c = context.Background()
tx, _ = testDao.BeginBiliDMTrans(c)
subtitlePub = &model.SubtitlePub{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.TxAddSubtitlePub(tx, subtitlePub)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
ctx.Reset(func() {
tx.Commit()
})
})
}
func TestDaoTxGetSubtitleOne(t *testing.T) {
convey.Convey("TxGetSubtitleOne", t, func(ctx convey.C) {
var (
c = context.Background()
tx, _ = testDao.BeginBiliDMTrans(c)
oid = int64(0)
tp = int32(0)
lan = uint8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.TxGetSubtitleOne(tx, oid, tp, lan)
})
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 TestDaoSubtitleLanAdd(t *testing.T) {
convey.Convey("SubtitleLanAdd", t, func(ctx convey.C) {
var (
c = context.Background()
subtitleLan = &model.SubtitleLan{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.SubtitleLanAdd(c, subtitleLan)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoUpsertWaveFrom(t *testing.T) {
convey.Convey("UpsertWaveFrom", t, func(ctx convey.C) {
var (
c = context.Background()
waveForm = &model.WaveForm{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.UpsertWaveFrom(c, waveForm)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoGetWaveForm(t *testing.T) {
convey.Convey("GetWaveForm", 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) {
waveForm, err := testDao.GetWaveForm(c, oid, tp)
ctx.Convey("Then err should be nil.waveForm should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(waveForm, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,385 @@
package dao
import (
"context"
xtime "go-common/library/time"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoSubject(t *testing.T) {
convey.Convey("Subject", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.Subject(c, tp, oid)
})
})
}
func TestDaoSubjects(t *testing.T) {
convey.Convey("Subjects", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oids = []int64{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.Subjects(c, tp, oids)
})
})
}
func TestDaoUptSubAttr(t *testing.T) {
convey.Convey("UptSubAttr", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oid = int64(0)
attr = int32(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
affect, err := testDao.UptSubAttr(c, tp, oid, attr)
ctx.Convey("Then err should be nil.affect should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affect, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoIncrSubMoveCount(t *testing.T) {
convey.Convey("IncrSubMoveCount", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oid = int64(0)
count = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
affect, err := testDao.IncrSubMoveCount(c, tp, oid, count)
ctx.Convey("Then err should be nil.affect should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affect, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoUpSubjectMCount(t *testing.T) {
convey.Convey("UpSubjectMCount", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oid = int64(0)
cnt = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
affect, err := testDao.UpSubjectMCount(c, tp, oid, cnt)
ctx.Convey("Then err should be nil.affect should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affect, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoUpSubjectPool(t *testing.T) {
convey.Convey("UpSubjectPool", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oid = int64(0)
childpool = int32(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
affect, err := testDao.UpSubjectPool(c, tp, oid, childpool)
ctx.Convey("Then err should be nil.affect should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affect, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoIncrSubjectCount(t *testing.T) {
convey.Convey("IncrSubjectCount", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oid = int64(0)
count = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
affect, err := testDao.IncrSubjectCount(c, tp, oid, count)
ctx.Convey("Then err should be nil.affect should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affect, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoDMIDs(t *testing.T) {
convey.Convey("DMIDs", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oid = int64(0)
ps = int64(0)
pe = int64(0)
limit = int64(0)
pool = int32(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.DMIDs(c, tp, oid, ps, pe, limit, pool)
})
})
}
func TestDaoIndexs(t *testing.T) {
convey.Convey("Indexs", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.Indexs(c, tp, oid)
})
})
}
func TestDaoIndexByid(t *testing.T) {
convey.Convey("IndexByid", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int8(0)
oid = int64(0)
dmid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.IndexByid(c, tp, oid, dmid)
})
})
}
func TestDaoIndexsByid(t *testing.T) {
convey.Convey("IndexsByid", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oid = int64(0)
dmids = []int64{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.IndexsByid(c, tp, oid, dmids)
})
})
}
func TestDaoJudgeIndex(t *testing.T) {
convey.Convey("JudgeIndex", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int8(0)
oid = int64(0)
ctime1 = xtime.Time(time.Now().Unix())
ctime2 = xtime.Time(time.Now().Unix())
prog1 = int32(0)
prog2 = int32(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.JudgeIndex(c, tp, oid, ctime1, ctime2, prog1, prog2)
})
})
}
func TestDaoContent(t *testing.T) {
convey.Convey("Content", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
dmid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
ct, err := testDao.Content(c, oid, dmid)
ctx.Convey("Then err should be nil.ct should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(ct, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoContents(t *testing.T) {
convey.Convey("Contents", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
dmids = []int64{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
ctsMap, err := testDao.Contents(c, oid, dmids)
ctx.Convey("Then err should be nil.ctsMap should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(ctsMap, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoContentsSpecial(t *testing.T) {
convey.Convey("ContentsSpecial", t, func(ctx convey.C) {
var (
c = context.Background()
dmids = []int64{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.ContentsSpecial(c, dmids)
})
})
}
func TestDaoUpdateDMStat(t *testing.T) {
convey.Convey("UpdateDMStat", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oid = int64(0)
state = int32(0)
dmids = []int64{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.UpdateDMStat(c, tp, oid, state, dmids)
})
})
}
func TestDaoUpdateUserDMStat(t *testing.T) {
convey.Convey("UpdateUserDMStat", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oid = int64(0)
mid = int64(0)
state = int32(0)
dmids = []int64{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.UpdateUserDMStat(c, tp, oid, mid, state, dmids)
})
})
}
func TestDaoUpdateDMPool(t *testing.T) {
convey.Convey("UpdateDMPool", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oid = int64(0)
pool = int32(0)
dmids = []int64{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.UpdateDMPool(c, tp, oid, pool, dmids)
})
})
}
func TestDaoUpdateDMAttr(t *testing.T) {
convey.Convey("UpdateDMAttr", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oid = int64(0)
dmid = int64(0)
attr = int32(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
affect, err := testDao.UpdateDMAttr(c, tp, oid, dmid, attr)
ctx.Convey("Then err should be nil.affect should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affect, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoDMCount(t *testing.T) {
convey.Convey("DMCount", t, func(ctx convey.C) {
var (
c = context.Background()
typ = int32(0)
oid = int64(0)
states = []int64{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.DMCount(c, typ, oid, states)
})
})
}
func TestDaoSpecialDmLocation(t *testing.T) {
convey.Convey("SpecialDmLocation", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.SpecialDmLocation(c, tp, oid)
})
})
}
func TestDaoSpecalDMs(t *testing.T) {
convey.Convey("SpecalDMs", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.SpecalDMs(c, tp, oid)
})
})
}
func TestDaoAddUpperConfig(t *testing.T) {
convey.Convey("AddUpperConfig", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
advPermit = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
affect, err := testDao.AddUpperConfig(c, mid, advPermit)
ctx.Convey("Then err should be nil.affect should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affect, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoUpperConfig(t *testing.T) {
convey.Convey("UpperConfig", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
advPermit, err := testDao.UpperConfig(c, mid)
ctx.Convey("Then err should be nil.advPermit should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(advPermit, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,44 @@
package dao
import (
"context"
"fmt"
"net/url"
"go-common/library/log"
"go-common/library/xstr"
)
const (
_notifyURI = "/api/notify/send.user.notify.do"
)
func (d *Dao) notifyURI() string {
return d.conf.Host.Message + _notifyURI
}
// SendNotify 发送站内信
func (d *Dao) SendNotify(c context.Context, title, content, dataType string, mids []int64) (err error) {
res := struct {
Code int `json:"code"`
Data struct {
TotalCount int
ErrorCount int
} `json:"data"`
}{}
params := url.Values{}
params.Set("mc", "1_8_2")
params.Set("title", title)
params.Set("data_type", dataType)
params.Set("context", content)
params.Set("mid_list", xstr.JoinInts(mids))
if err = d.httpCli.Post(c, d.notifyURI(), "", params, &res); err != nil {
log.Error("d.httpClient.Post(%s,%v,%d)", d.notifyURI(), params, err)
return
}
if res.Code != 0 {
err = fmt.Errorf("res.Code:;%d", res.Code)
log.Error("d.httpClient.Post(%s,%v,%v,%d)", d.notifyURI(), params, err, res.Code)
}
return
}

View File

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

View File

@@ -0,0 +1,171 @@
package dao
import (
"context"
"fmt"
"go-common/library/cache/redis"
"go-common/library/ecode"
"go-common/library/log"
)
const (
// dm xml list v1
_prefixDM = "dm_v1_%d_%d" // dm_v1_type_oid
_broadcastLimitFmt = "b_room_%d_%d" // b_room_type_oid
)
func keyDM(tp int32, oid int64) (key string) {
return fmt.Sprintf(_prefixDM, tp, oid)
}
func keyBroadcastLimit(tp int32, oid int64) (key string) {
return fmt.Sprintf(_broadcastLimitFmt, tp, oid)
}
// DMCache 获取redis列表中的弹幕.
func (d *Dao) DMCache(c context.Context, tp int32, oid int64) (res [][]byte, err error) {
conn := d.dmRds.Get(c)
key := keyDM(tp, oid)
if res, err = redis.ByteSlices(conn.Do("ZRANGE", key, 0, -1)); err != nil {
log.Error("conn.Do(ZRANGE %s) error(%v)", key, err)
}
conn.Close()
return
}
// ExpireDMCache expire dm.
func (d *Dao) ExpireDMCache(c context.Context, tp int32, oid int64) (ok bool, err error) {
key := keyDM(tp, oid)
conn := d.dmRds.Get(c)
if ok, err = redis.Bool(conn.Do("EXPIRE", key, d.dmRdsExpire)); err != nil {
log.Error("conn.Do(EXPIRE %s) error(%v)", key, err)
}
conn.Close()
return
}
// TrimDMCache 从redis列表中pop掉count条弹幕.
func (d *Dao) TrimDMCache(c context.Context, tp int32, oid, count int64) (err error) {
conn := d.dmRds.Get(c)
key := keyDM(tp, oid)
if _, err = conn.Do("ZREMRANGEBYRANK", key, 0, count-1); err != nil {
log.Error("conn.Do(ZREMRANGEBYRANK %s) error(%v)", key, err)
}
conn.Close()
return
}
// IncrPubCnt increase pub count of user.
func (d *Dao) IncrPubCnt(c context.Context, mid, color int64, mode, fontsize int32, ip, msg string) (err error) {
conn := d.dmRds.Get(c)
defer conn.Close()
key := keyPubCntLock(mid, color, mode, fontsize, ip, msg)
if err = conn.Send("INCR", key); err != nil {
log.Error("conn.Send(INCR %s) error(%v)", key, err)
return
}
if err = conn.Send("EXPIRE", key, 300); err != nil {
log.Error("conn.Send(EXPIRE %s) error(%v)", key, err)
return
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush() error(%v)", err)
return
}
for i := 0; i < 2; i++ {
if _, err = conn.Receive(); err != nil {
log.Error("conn.Receive() error(%v)", err)
return
}
}
return
}
// PubCnt get dm pub count of user.
func (d *Dao) PubCnt(c context.Context, mid, color int64, mode, fontsize int32, ip, msg string) (count int64, err error) {
conn := d.dmRds.Get(c)
defer conn.Close()
key := keyPubCntLock(mid, color, mode, fontsize, ip, msg)
if count, err = redis.Int64(conn.Do("GET", key)); err != nil {
if err == redis.ErrNil {
err = nil
} else {
log.Error("conn.Do(GET %s) error(%v)", key, err)
}
return
}
return
}
// IncrCharPubCnt increase character pub count of user.
func (d *Dao) IncrCharPubCnt(c context.Context, mid, oid int64) (err error) {
conn := d.dmRds.Get(c)
defer conn.Close()
key := keyCharPubLock(mid, oid)
if err = conn.Send("INCR", key); err != nil {
log.Error("conn.Send(INCR %s) error(%v)", key, err)
return
}
if err = conn.Send("EXPIRE", key, 60); err != nil {
log.Error("conn.Send(EXPIRE %s) error(%v)", key, err)
return
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush() error(%v)", err)
return
}
for i := 0; i < 2; i++ {
if _, err = conn.Receive(); err != nil {
log.Error("conn.Receive() error(%v)", err)
return
}
}
return
}
// CharPubCnt get character pub count of user.
func (d *Dao) CharPubCnt(c context.Context, mid, oid int64) (count int64, err error) {
conn := d.dmRds.Get(c)
defer conn.Close()
key := keyCharPubLock(mid, oid)
if count, err = redis.Int64(conn.Do("GET", key)); err != nil {
if err == redis.ErrNil {
err = nil
} else {
log.Error("conn.Do(GET %s) error(%v)", key, err)
}
return
}
return
}
// DelCharPubCnt delete char
func (d *Dao) DelCharPubCnt(c context.Context, mid, oid int64) (err error) {
conn := d.dmRds.Get(c)
key := keyCharPubLock(mid, oid)
if _, err = conn.Do("DEL", key); err != nil {
log.Error("conn.Do(DEL %s) error(%v)", key, err)
}
conn.Close()
return
}
// BroadcastLimit .
func (d *Dao) BroadcastLimit(c context.Context, oid int64, tp int32, count, interval int) (err error) {
conn := d.dmRds.Get(c)
key := keyBroadcastLimit(tp, oid)
defer conn.Close()
incred, err := redis.Int64(conn.Do("INCR", key))
if err != nil {
return nil
}
if incred == 1 {
conn.Do("EXPIRE", key, interval)
}
if incred > int64(count) {
return ecode.LimitExceed
}
return
}

View File

@@ -0,0 +1,75 @@
package dao
import (
"context"
"strconv"
"go-common/app/interface/main/dm2/model"
"go-common/library/cache/redis"
"go-common/library/log"
)
const (
_prefixRecent = "dm_rct_"
)
func keyRecent(mid int64) string {
return _prefixRecent + strconv.FormatInt(mid, 10)
}
// RecentDM get recent dm of up.
func (d *Dao) RecentDM(c context.Context, mid, start, end int64) (dms []*model.DM, oids []int64, total int64, err error) {
var (
conn = d.dmRctRds.Get(c)
key = keyRecent(mid)
oidMap = make(map[int64]struct{})
)
defer conn.Close()
if err = conn.Send("ZREVRANGE", key, start, end); err != nil {
log.Error("conn.Send(ZREVRANGE %s) error(%s)", key, err)
return
}
if err = conn.Send("ZCARD", key); err != nil {
log.Error("conn.Send(ZCARD %s) error(%v)", key, err)
return
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush() error(%v)", err)
return
}
values, err := redis.ByteSlices(conn.Receive())
if err != nil {
log.Error("conn.Receive(%s) error(%v)", key, err)
return
}
if total, err = redis.Int64(conn.Receive()); err != nil {
log.Error("conn.Receive(%s) error(%v)", key, err)
return
}
for _, value := range values {
dm := &model.DM{}
if err = dm.Unmarshal(value); err != nil {
log.Error("dm.Unmarshal(%s) error(%v)", value, err)
return
}
dms = append(dms, dm)
if _, ok := oidMap[dm.Oid]; !ok {
oidMap[dm.Oid] = struct{}{}
oids = append(oids, dm.Oid)
}
}
return
}
// TrimUpRecent zrange remove recent dm of up.
func (d *Dao) TrimUpRecent(c context.Context, mid, count int64) (err error) {
var (
conn = d.dmRctRds.Get(c)
key = keyRecent(mid)
)
defer conn.Close()
if _, err = conn.Do("ZREMRANGEBYRANK", key, 0, count-1); err != nil {
log.Error("conn.Do(ZREMRANGEBYRANK %s) error(%v)", key, err)
}
return
}

View File

@@ -0,0 +1,52 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaokeyRecent(t *testing.T) {
convey.Convey("keyRecent", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyRecent(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoRecentDM(t *testing.T) {
convey.Convey("RecentDM", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
start = int64(0)
end = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.RecentDM(c, mid, start, end)
})
})
}
func TestDaoTrimUpRecent(t *testing.T) {
convey.Convey("TrimUpRecent", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
count = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.TrimUpRecent(c, mid, count)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,209 @@
package dao
import (
"context"
"encoding/xml"
"fmt"
"go-common/app/interface/main/dm2/model"
"go-common/library/cache/redis"
"go-common/library/log"
)
const (
_keyIdx = "i_%d_%d_%d_%d" // normal dm segment sortedset(s_type_oid_cnt_n, ctime, dmid)
_keyIdxSub = "s_%d_%d" // subtitle dm sortedset(s_type_oid, progress, dmid)
_keyIdxSpe = "spe_%d_%d" // special dm sortedset(spe_type_oid, progress,dmid)
_keyIdxContent = "c_%d_%d" // dm content hash(d_type_oid, dmid, xml)
)
func keyIdx(tp int32, oid, cnt, n int64) string {
return fmt.Sprintf(_keyIdx, tp, oid, cnt, n)
}
// keyIdxSub return dm idx key.
func keyIdxSub(tp int32, oid int64) string {
return fmt.Sprintf(_keyIdxSub, tp, oid)
}
// keyIdxContent return key of different dm.
func keyIdxContent(tp int32, oid int64) string {
return fmt.Sprintf(_keyIdxContent, tp, oid)
}
func keyIdxSpecial(tp int32, oid int64) string {
return fmt.Sprintf(_keyIdxSpe, tp, oid)
}
// DMIDSubtitlesCache return subtitle dm ids.
func (d *Dao) DMIDSubtitlesCache(c context.Context, tp int32, oid int64, ps, pe, limit int64) (dmids []int64, err error) {
var (
conn = d.dmSegRds.Get(c)
keySub = keyIdxSub(tp, oid)
)
defer conn.Close()
if dmids, err = redis.Int64s(conn.Do("ZRANGEBYSCORE", keySub, ps, pe, "LIMIT", 0, limit)); err != nil {
log.Error("conn.DO(ZRANGEBYSCORE %s) error(%v)", keySub, err)
}
if len(dmids) > 0 {
PromCacheHit("dm_seg_dmid", 1)
} else {
PromCacheMiss("dm_seg_dmid", 1)
}
return
}
// DMIDCache return dm index id.
func (d *Dao) DMIDCache(c context.Context, tp int32, oid int64, cnt, n, limit int64) (dmids []int64, err error) {
var (
conn = d.dmSegRds.Get(c)
keyIdx = keyIdx(tp, oid, cnt, n)
)
defer conn.Close()
if dmids, err = redis.Int64s(conn.Do("ZRANGE", keyIdx, 0, -1)); err != nil {
log.Error("DMIDSPCache.conn.DO(ZRANGEBYSCORE %s) error(%v)", keyIdx, err)
}
if len(dmids) > 0 {
PromCacheHit("dm_seg_dmid", 1)
} else {
PromCacheMiss("dm_seg_dmid", 1)
}
return
}
// IdxContentCache get xml info by dmid.
func (d *Dao) IdxContentCache(c context.Context, tp int32, oid int64, dmids []int64) (res []byte, missed []int64, err error) {
var (
k int
dmid int64
values [][]byte
key = keyIdxContent(tp, oid)
args = []interface{}{key}
)
for _, dmid = range dmids {
args = append(args, dmid)
}
conn := d.dmSegRds.Get(c)
defer conn.Close()
if values, err = redis.ByteSlices(conn.Do("HMGET", args...)); err != nil {
log.Error("conn.Do(HMGET %v) error(%v)", args, err)
if err == redis.ErrNil {
return nil, nil, nil
}
return
}
for k, dmid = range dmids {
if len(values[k]) == 0 {
missed = append(missed, dmid)
continue
}
res = append(res, values[k]...)
}
PromCacheMiss("dmid_content", int64(len(missed)))
PromCacheHit("dmid_content", int64(len(dmids)-len(missed)))
return
}
// IdxContentCacheV2 get elems info by dmid.
func (d *Dao) IdxContentCacheV2(c context.Context, tp int32, oid int64, dmids []int64) (elems []*model.Elem, missed []int64, err error) {
var (
k int
dmid int64
values [][]byte
key = keyIdxContent(tp, oid)
args = []interface{}{key}
)
for _, dmid = range dmids {
args = append(args, dmid)
}
conn := d.dmSegRds.Get(c)
defer conn.Close()
if values, err = redis.ByteSlices(conn.Do("HMGET", args...)); err != nil {
if err == redis.ErrNil {
err = nil
missed = dmids
} else {
log.Error("conn.Do(HMGET %v) error(%v)", args, err)
}
return
}
for k, dmid = range dmids {
if len(values[k]) == 0 {
missed = append(missed, dmid)
continue
}
elem, err := d.xmlToElem(values[k])
if err != nil {
missed = append(missed, dmid)
continue
}
elems = append(elems, elem)
}
PromCacheMiss("dmid_elem", int64(len(missed)))
PromCacheHit("dmid_elem", int64(len(dmids)-len(missed)))
return
}
// 在缓存过渡期将<d p="弹幕ID,弹幕属性,播放时间,弹幕模式,字体大小,颜色,发送时间,弹幕池,用户hash id">弹幕内容</d>
// 装换为 model.Elem结构
func (d *Dao) xmlToElem(data []byte) (e *model.Elem, err error) {
var v struct {
XMLName xml.Name `xml:"d"`
Attribute string `xml:"p,attr"`
Content string `xml:",chardata"`
}
if err = xml.Unmarshal(data, &v); err != nil {
return
}
e = &model.Elem{Content: v.Content, Attribute: v.Attribute}
return
}
// AddIdxContentCache add index content cache to redis.
func (d *Dao) AddIdxContentCache(c context.Context, tp int32, oid int64, dms []*model.DM, realname bool) (err error) {
var (
key string
conn = d.dmSegRds.Get(c)
)
defer conn.Close()
for _, dm := range dms {
key = keyIdxContent(tp, oid)
if err = conn.Send("HSET", key, dm.ID, dm.ToXMLSeg(realname)); err != nil {
log.Error("conn.Send(HSET %s,%v) error(%v)", key, dm, err)
return
}
}
if err = conn.Send("EXPIRE", key, d.dmSegExpire); err != nil {
log.Error("conn.Send(EXPIRE %s) error(%v)", key, err)
return
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush() error(%v)", err)
return
}
for i := 0; i <= len(dms); i++ {
if _, err = conn.Receive(); err != nil {
log.Error("conn.Receive() error(%v)", err)
return
}
}
return
}
// DMIDSpecialsCache return special dmids
func (d *Dao) DMIDSpecialsCache(c context.Context, tp int32, oid int64) (dmids []int64, err error) {
var (
conn = d.dmSegRds.Get(c)
keySpe = keyIdxSpecial(tp, oid)
)
defer conn.Close()
if dmids, err = redis.Int64s(conn.Do("ZRANGE", keySpe, 0, -1)); err != nil {
log.Error("conn.DO(ZRANGE %s) error(%v)", keySpe, err)
}
if len(dmids) > 0 {
PromCacheHit("dm_spe_dmid", 1)
} else {
PromCacheMiss("dm_spe_dmid", 1)
}
return
}

View File

@@ -0,0 +1,46 @@
package dao
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestDMIDCache(t *testing.T) {
var (
tp int32 = 1
oid int64 = 1508
cnt int64 = 26
num int64 = 1
c = context.TODO()
)
_, err := testDao.DMIDCache(c, tp, oid, cnt, num, 100)
if err != nil {
t.Fatalf("d.DMIDCache(%d %d %d %d) error(%v)", tp, oid, cnt, num, err)
}
}
func TestIdxContentCache(t *testing.T) {
var (
tp int32 = 1
oid int64 = 1508
c = context.TODO()
dmids = []int64{2355015081, 2356915089}
)
res, missed, err := testDao.IdxContentCache(c, tp, oid, dmids)
if err != nil {
t.Errorf("d.IdxContentCache(%d %d %v) error(%v)", tp, oid, dmids, err)
t.FailNow()
}
t.Logf("res:%s, missed:%v", res, missed)
}
func TestXMLToElem(t *testing.T) {
Convey("convert xml tag to elem struct", t, func() {
s := []byte(`<d p="1,1,1,1,11,111,11,1,23123123">弹幕内容</d>`)
elem, err := testDao.xmlToElem(s)
So(err, ShouldBeNil)
t.Logf("%+v", elem)
})
}

View File

@@ -0,0 +1,194 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaokeyDM(t *testing.T) {
convey.Convey("keyDM", t, func(ctx convey.C) {
var (
tp = int32(0)
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
key := keyDM(tp, oid)
ctx.Convey("Then key should not be nil.", func(ctx convey.C) {
ctx.So(key, convey.ShouldNotBeNil)
})
})
})
}
func TestDaokeyBroadcastLimit(t *testing.T) {
convey.Convey("keyBroadcastLimit", t, func(ctx convey.C) {
var (
tp = int32(0)
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
key := keyBroadcastLimit(tp, oid)
ctx.Convey("Then key should not be nil.", func(ctx convey.C) {
ctx.So(key, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoDMCache(t *testing.T) {
convey.Convey("DMCache", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := testDao.DMCache(c, tp, oid)
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)
})
})
})
}
func TestDaoExpireDMCache(t *testing.T) {
convey.Convey("ExpireDMCache", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
ok, err := testDao.ExpireDMCache(c, tp, oid)
ctx.Convey("Then err should be nil.ok should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(ok, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoTrimDMCache(t *testing.T) {
convey.Convey("TrimDMCache", t, func(ctx convey.C) {
var (
c = context.Background()
tp = int32(0)
oid = int64(0)
count = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.TrimDMCache(c, tp, oid, count)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoIncrPubCnt(t *testing.T) {
convey.Convey("IncrPubCnt", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
color = int64(0)
mode = int32(0)
fontsize = int32(0)
ip = ""
msg = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.IncrPubCnt(c, mid, color, mode, fontsize, ip, msg)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoPubCnt(t *testing.T) {
convey.Convey("PubCnt", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
color = int64(0)
mode = int32(0)
fontsize = int32(0)
ip = ""
msg = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
count, err := testDao.PubCnt(c, mid, color, mode, fontsize, ip, msg)
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 TestDaoIncrCharPubCnt(t *testing.T) {
convey.Convey("IncrCharPubCnt", 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) {
err := testDao.IncrCharPubCnt(c, mid, oid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoCharPubCnt(t *testing.T) {
convey.Convey("CharPubCnt", 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) {
count, err := testDao.CharPubCnt(c, mid, oid)
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 TestDaoDelCharPubCnt(t *testing.T) {
convey.Convey("DelCharPubCnt", 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) {
err := testDao.DelCharPubCnt(c, mid, oid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoBroadcastLimit(t *testing.T) {
convey.Convey("BroadcastLimit", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
tp = int32(0)
count = int(0)
interval = int(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.BroadcastLimit(c, oid, tp, count, interval)
})
})
}

View File

@@ -0,0 +1,418 @@
package dao
import (
"context"
"fmt"
"strconv"
"strings"
"time"
"go-common/app/interface/main/dm2/model"
"go-common/library/database/elastic"
"go-common/library/log"
"go-common/library/xstr"
)
var (
_dataTimeFormat = "2006-01-02 15:03:04"
_subtitleFields = []string{"oid", "id"}
_dmRecentFields = []string{"attr", "color", "ctime", "fontsize", "id", "mid", "mode", "msg", "mtime", "oid", "pool", "progress", "state", "type", "pid"}
)
func hisDateIndex(month string) string {
return "dm_date_" + strings.Replace(month, "-", "_", -1)
}
// SearchDMHisIndex get dm date index by oid from search.
func (d *Dao) SearchDMHisIndex(c context.Context, tp int32, oid int64, month string) (dates []string, err error) {
var (
pn, ps = 1, 31
res model.SearchHistoryIdxResult
)
req := d.elastic.NewRequest("dm_date")
req.Fields("date").WhereEq("oid", oid)
req.Index(hisDateIndex(month)).Pn(pn).Ps(ps).Order("date", "asc")
if err = req.Scan(c, &res); err != nil {
log.Error("elastic search(%s) error(%v)", req.Params(), err)
return
}
for _, v := range res.Result {
dates = append(dates, v.Date)
}
return
}
// SearchDMHistory get history dmid from search.
// 搜索定制api改动需要沟通
func (d *Dao) SearchDMHistory(c context.Context, tp int32, oid, ctimeTo int64, pn, ps int) (dmids []int64, err error) {
var (
res model.SearchHistoryResult
end = time.Unix(ctimeTo, 0).Format("2006-01-02 15:04:05")
)
req := d.elastic.NewRequest("dm_history")
req.Index(fmt.Sprintf("dm_search_%03d", oid%_indexSharding))
req.Fields("id").WhereEq("oid", oid).WhereIn("state", []int64{0, 2, 6})
req.WhereRange("ctime", nil, end, elastic.RangeScopeLcRc)
req.Pn(pn).Ps(ps).Order("ctime", "desc")
if err = req.Scan(c, &res); err != nil {
log.Error("elastic search(%s) error(%v)", req.Params(), err)
return
}
for _, v := range res.Result {
dmids = append(dmids, v.ID)
}
return
}
// SearchDM 搜索弹幕
func (d *Dao) SearchDM(c context.Context, p *model.SearchDMParams) (res *model.SearchDMData, err error) {
req := d.elastic.NewRequest("dm_search")
req.Fields("id").Index(fmt.Sprintf("dm_search_%03d", p.Oid%_indexSharding)).WhereEq("oidstr", p.Oid)
if p.Mids != "" {
mids, _ := xstr.SplitInts(p.Mids)
req.WhereIn("mid", mids)
}
if p.State != "" {
states, _ := xstr.SplitInts(p.State)
req.WhereIn("state", states)
}
if p.Mode != "" {
modes, _ := xstr.SplitInts(p.Mode)
req.WhereIn("mode", modes)
}
if p.Pool != "" {
pools, _ := xstr.SplitInts(p.Pool)
req.WhereIn("pool", pools)
}
if p.Attrs != "" {
attrs, _ := xstr.SplitInts(p.Attrs)
req.WhereIn("attr_format", attrs)
}
req.WhereEq("type", p.Type)
switch {
case p.ProgressFrom != model.CondIntNil && p.ProgressTo != model.CondIntNil:
req.WhereRange("progress_long", p.ProgressFrom, p.ProgressTo, elastic.RangeScopeLcRc)
case p.ProgressFrom != model.CondIntNil:
req.WhereRange("progress_long", p.ProgressFrom, nil, elastic.RangeScopeLcRc)
case p.ProgressTo != model.CondIntNil:
req.WhereRange("progress_long", nil, p.ProgressTo, elastic.RangeScopeLcRc)
}
req.WhereRange("ctime", p.CtimeFrom, p.CtimeTo, elastic.RangeScopeLcRc)
if p.Keyword != "" {
req.WhereLike([]string{"msg"}, []string{p.Keyword}, true, elastic.LikeLevelHigh)
req.OrderScoreFirst(true)
}
if p.Order == "progress" {
p.Order = "progress_long"
}
req.Order(p.Order, p.Sort)
req.Pn(int(p.Pn)).Ps(int(p.Ps))
res = &model.SearchDMData{}
if err = req.Scan(c, &res); err != nil {
log.Error("search params(%s), error(%v)", req.Params(), err)
}
return
}
// UptSearchDMState update dm search state
func (d *Dao) UptSearchDMState(c context.Context, dmids []int64, oid int64, state, tp int32) (err error) {
upt := d.elastic.NewUpdate("dm_search")
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_search_%03d", oid%_indexSharding), data)
}
if err = upt.Do(c); err != nil {
log.Error("update.Do() params(%s) error(%v)", upt.Params(), err)
}
return
}
// UptSearchDMPool update dm search pool
func (d *Dao) UptSearchDMPool(c context.Context, dmids []int64, oid int64, pool, tp int32) (err error) {
upt := d.elastic.NewUpdate("dm_search")
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_search_%03d", oid%_indexSharding), data)
}
if err = upt.Do(c); err != nil {
log.Error("update.Do() params(%s) error(%v)", upt.Params(), err)
}
return
}
// UptSearchDMAttr update dm search attr
func (d *Dao) UptSearchDMAttr(c context.Context, dmids []int64, oid int64, attr, tp int32) (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.elastic.NewUpdate("dm_search")
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_search_%03d", oid%_indexSharding), data)
}
if err = upt.Do(c); err != nil {
log.Error("update.Do() params(%s) error(%v)", upt.Params(), err)
}
return
}
// SearchSubtitles .
func (d *Dao) SearchSubtitles(c context.Context, page, size int32, mid int64, upMids []int64, aid, oid int64, tp int32, status []int64) (res *model.SearchSubtitleResult, err error) {
var (
req *elastic.Request
fields []string
)
fields = _subtitleFields
req = d.elastic.NewRequest("dm_subtitle").Index("subtitle").Fields(fields...).Pn(int(page)).Ps(int(size))
if mid > 0 {
req.WhereEq("mid", mid)
}
if aid > 0 {
req.WhereEq("aid", aid)
}
if oid > 0 {
req.WhereEq("oid", oid)
req.WhereEq("type", tp)
}
switch {
case len(upMids) > 0 && len(status) > 0:
cmbs := &elastic.Combo{}
cmbu := &elastic.Combo{}
var (
statusInf []interface{}
upMidsInf []interface{}
)
for _, s := range status {
statusInf = append(statusInf, s)
}
for _, s := range upMids {
upMidsInf = append(upMidsInf, s)
}
cmbs.ComboIn([]map[string][]interface{}{
{"status": statusInf},
})
cmbu.ComboIn([]map[string][]interface{}{
{"up_mid": upMidsInf},
})
req = req.WhereCombo(cmbs.MinIn(1).MinAll(1), cmbu.MinIn(1).MinAll(1))
case len(upMids) > 0:
req.WhereIn("up_mid", upMids)
case len(status) > 0:
req.WhereIn("status", status)
}
req.Order("mtime", "desc")
if err = req.Scan(c, &res); err != nil {
log.Error("elastic search(%s) error(%v)", req.Params(), err)
return
}
return
}
// CountSubtitles .
func (d *Dao) CountSubtitles(c context.Context, mid int64, upMids []int64, aid, oid int64, tp int32) (countSubtitle *model.CountSubtitleResult, err error) {
var (
req *elastic.Request
fields []string
res map[string]interface{}
_searchStatus = []string{
fmt.Sprint(model.SubtitleStatusDraft),
fmt.Sprint(model.SubtitleStatusToAudit),
fmt.Sprint(model.SubtitleStatusAuditBack),
fmt.Sprint(model.SubtitleStatusPublish),
fmt.Sprint(model.SubtitleStatusCheckToAudit),
fmt.Sprint(model.SubtitleStatusCheckPublish),
fmt.Sprint(model.SubtitleStatusManagerBack),
}
result map[string]interface{}
groupStatus []interface{}
itemStatus map[string]interface{}
ok bool
)
req = d.elastic.NewRequest("dm_subtitle").Index("subtitle").Fields(fields...).Pn(0).Ps(0)
if mid > 0 {
req.WhereEq("mid", mid)
}
if aid > 0 {
req.WhereEq("aid", aid)
}
if oid > 0 {
req.WhereEq("oid", oid)
req.WhereEq("type", tp)
}
if len(upMids) > 0 {
req.WhereIn("up_mid", upMids)
}
req = req.GroupBy(elastic.EnhancedModeGroupBy, "status", nil).WhereIn("status", _searchStatus)
if err = req.Scan(c, &res); err != nil {
log.Error("elastic search(%s) error(%v)", req.Params(), err)
return
}
countSubtitle = &model.CountSubtitleResult{}
if result, ok = res["result"].(map[string]interface{}); !ok {
return
}
if groupStatus, ok = result["group_by_status"].([]interface{}); !ok {
return
}
for _, item := range groupStatus {
if itemStatus, ok = item.(map[string]interface{}); ok {
docCount, _ := itemStatus["doc_count"].(float64)
switch itemStatus["key"] {
case fmt.Sprint(model.SubtitleStatusDraft):
countSubtitle.Draft += int64(docCount)
case fmt.Sprint(model.SubtitleStatusToAudit):
countSubtitle.ToAudit += int64(docCount)
case fmt.Sprint(model.SubtitleStatusAuditBack):
countSubtitle.AuditBack += int64(docCount)
case fmt.Sprint(model.SubtitleStatusPublish):
countSubtitle.Publish += int64(docCount)
case fmt.Sprint(model.SubtitleStatusCheckToAudit):
countSubtitle.ToAudit += int64(docCount)
case fmt.Sprint(model.SubtitleStatusCheckPublish):
countSubtitle.Publish += int64(docCount)
case fmt.Sprint(model.SubtitleStatusManagerBack):
countSubtitle.AuditBack += int64(docCount)
}
}
}
return
}
// UptSearchRecentState .
func (d *Dao) UptSearchRecentState(c context.Context, dmids []int64, oid int64, state, tp int32) (err error) {
upt := d.elastic.NewUpdate("dm_home")
year, month, _ := time.Now().Date()
yearPre, monthPre, _ := time.Now().AddDate(0, -1, 0).Date()
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
}
// UptSearchRecentAttr .
func (d *Dao) UptSearchRecentAttr(c context.Context, dmids []int64, oid int64, attr, tp int32) (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.elastic.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
}
// UptSearchRecentPool .
func (d *Dao) UptSearchRecentPool(c context.Context, dmids []int64, oid int64, pool, tp int32) (err error) {
upt := d.elastic.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
}
// SearhcDmRecent .
func (d *Dao) SearhcDmRecent(c context.Context, param *model.SearchRecentDMParam) (res *model.SearchRecentDMResult, err error) {
var (
req *elastic.Request
)
year, month, _ := time.Now().Date()
yearPre, monthPre, _ := time.Now().AddDate(0, -1, 0).Date()
req = d.elastic.NewRequest("dm_home").Index(fmt.Sprintf("dm_home_%v,dm_home_%v",
fmt.Sprintf("%d_%02d", year, int(month)),
fmt.Sprintf("%d_%02d", yearPre, int(monthPre)),
)).Fields(_dmRecentFields...).Pn(param.Pn).Ps(param.Ps)
if param.Type > 0 {
req.WhereEq("type", param.Type)
}
if param.UpMid > 0 {
req.WhereEq("o_mid", param.UpMid)
}
if len(param.States) > 0 {
req.WhereIn("state", param.States)
}
req.WhereRange("ctime", time.Now().Local().AddDate(0, 0, -30).Format(_dataTimeFormat), time.Now().Local().Format(_dataTimeFormat), elastic.RangeScopeLcRo)
req.Order(param.Field, param.Sort)
res = &model.SearchRecentDMResult{}
if err = req.Scan(c, &res); err != nil {
log.Error("search params(%s), error(%v)", req.Params(), err)
}
return
}

View File

@@ -0,0 +1,106 @@
package dao
import (
"context"
"testing"
"go-common/app/interface/main/dm2/model"
"time"
. "github.com/smartystreets/goconvey/convey"
)
func TestSearchDM(t *testing.T) {
p := &model.SearchDMParams{
Oid: 10131156,
Mids: "",
Keyword: "",
ProgressFrom: model.CondIntNil,
ProgressTo: model.CondIntNil,
CtimeFrom: "",
CtimeTo: "",
Pn: 1,
Ps: 100,
State: "0",
Type: 1,
Mode: "",
Sort: "desc",
Order: "ctime",
Pool: "",
Attrs: "",
}
Convey("", t, func() {
res, err := testDao.SearchDM(context.TODO(), p)
So(err, ShouldBeNil)
So(res, ShouldNotBeEmpty)
t.Logf("%+v", res.Page)
for i, v := range res.Result {
t.Logf("%d %v", i, v)
}
})
}
func TestSearchDMHisIndex(t *testing.T) {
Convey("search dm history index", t, func() {
dates, err := testDao.SearchDMHisIndex(context.TODO(), 1, 10109227, "2018-03")
So(err, ShouldBeNil)
So(dates, ShouldNotBeEmpty)
t.Log(dates)
})
}
func TestSearchDMHistory(t *testing.T) {
Convey("search dm history", t, func() {
ctime, err := time.Parse("2006-01-02 15:04:05", "2016-08-03 23:59:59")
if err != nil {
t.Fail()
}
dmids, err := testDao.SearchDMHistory(context.TODO(), 1, 1221, ctime.Unix(), 1, 100)
So(err, ShouldBeNil)
So(dmids, ShouldNotBeEmpty)
t.Log(dmids)
})
}
func TestUptSearchDMPool(t *testing.T) {
Convey("update search dm pool", t, func() {
err := testDao.UptSearchDMPool(context.TODO(), []int64{416894555258883, 372530664701955}, 10131156, 1, 1)
So(err, ShouldBeNil)
})
}
func TestUptSearchDMState(t *testing.T) {
Convey("update search dm state", t, func() {
err := testDao.UptSearchDMState(context.TODO(), []int64{372412118466563}, 10131156, 1, 1)
So(err, ShouldBeNil)
})
}
func TestUptSearchDMAttr(t *testing.T) {
Convey("update search dm attr", t, func() {
err := testDao.UptSearchDMAttr(context.TODO(), []int64{372412118466563}, 10131156, 0, 1)
So(err, ShouldBeNil)
})
}
func TestSearchSubtitles(t *testing.T) {
Convey("search subtitle", t, func() {
res, err := testDao.SearchSubtitles(context.TODO(), 1, 10, 0, nil, 0, 0, 0, nil)
So(err, ShouldBeNil)
t.Logf("page:%+v", res.Page)
t.Logf("results:%v", len(res.Results))
for _, rs := range res.Results {
t.Logf("rs:%+v", rs)
}
})
}
func TestCountSubtitles(t *testing.T) {
Convey("search subtitle", t, func() {
res, err := testDao.CountSubtitles(context.TODO(), 0, nil, 0, 0, 0)
So(err, ShouldBeNil)
t.Logf("page:%+v", res)
})
}

View File

@@ -0,0 +1,74 @@
package dao
import (
"bytes"
"context"
"encoding/json"
"fmt"
"go-common/library/ecode"
"go-common/library/log"
"net/http"
)
const (
_uposURL = "api/v1/task/push/audiowaveform"
_uposBfsFmt = "subtitle/waveform_%d_%d.pcm"
_uposCallback = "x/internal/v2/dm/subtitle/upos/callback"
_defaultPixelDensity = 20
)
// UposReq .
type UposReq struct {
Cid int64 `json:"cid"`
SaveTo string `json:"saveto"`
CallbackURL string `json:"callback_url"`
PixelDensity int32 `json:"pixel_density"`
}
// UposResp .
type UposResp struct {
Code int32 `json:"code"`
Message string `json:"message"`
}
// Upos .
func (d *Dao) Upos(c context.Context, oid int64) (saveTo string, err error) {
var (
req *http.Request
bs []byte
resp []byte
)
saveTo = fmt.Sprintf(_uposBfsFmt, oid, 1)
params := &UposReq{
Cid: oid,
SaveTo: fmt.Sprintf("bfs://%s", saveTo),
CallbackURL: fmt.Sprintf("%s/%s?oid=%d", d.conf.Host.Self, _uposCallback, oid),
PixelDensity: _defaultPixelDensity,
}
if bs, err = json.Marshal(&params); err != nil {
log.Error("params(%+v),error(%v)", params, err)
return
}
if req, err = http.NewRequest(http.MethodPost, fmt.Sprintf("%s/%s", d.conf.Host.Upos, _uposURL), bytes.NewReader(bs)); err != nil {
log.Error("http.NewReques.error(%v)", err)
return
}
if resp, err = d.httpCli.Raw(c, req); err != nil {
log.Error("d.httpCli.Raw.error(%v)", err)
return
}
uposResp := &UposResp{}
if err = json.Unmarshal(resp, &uposResp); err != nil {
log.Error("params(%s),error(%v)", resp, err)
return
}
if uposResp.Code != 0 {
err = ecode.SubtitleWaveFormFailed
log.Error("d.Upos,error(%v),info(%s)", err, uposResp.Message)
}
return
}

View File

@@ -0,0 +1,16 @@
package dao
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestUpos(t *testing.T) {
Convey("test upos", t, func() {
saveTo, err := testDao.Upos(context.TODO(), 1111)
So(err, ShouldBeNil)
t.Logf("%+v", saveTo)
})
}

View File

@@ -0,0 +1,72 @@
package dao
import (
"context"
"fmt"
"time"
"go-common/app/interface/main/dm2/model"
"go-common/library/log"
"go-common/library/net/metadata"
"go-common/library/queue/databus/report"
)
const (
_businessUserLogDm = 161
// dm log
_typeUserLogDm = 1
_actionUserLogDmPost = "danmu_post"
// garbage dm
_typeUserLogGarbageDm = 2
_actionUserLogGarbageDm = "danmu_garbage"
)
func init() {
report.InitUser(nil)
}
// ReportDmGarbageLog report garbage dm
func (d *Dao) ReportDmGarbageLog(c context.Context, dm *model.DM) (err error) {
return d.reportUserLog(c, dm, _typeUserLogGarbageDm, _actionUserLogGarbageDm)
}
// ReportDmLog report dm post log
func (d *Dao) ReportDmLog(c context.Context, dm *model.DM) (err error) {
return d.reportUserLog(c, dm, _typeUserLogDm, _actionUserLogDmPost)
}
func (d *Dao) reportUserLog(c context.Context, dm *model.DM, userLogType int, userLogAction string) (err error) {
var (
remoteIP, remoteAddr = metadata.String(c, metadata.RemoteIP), metadata.String(c, metadata.RemotePort)
msg string
)
if dm.Content == nil {
return
}
msg = dm.Content.Msg
if dm.ContentSpe != nil {
msg = dm.ContentSpe.Msg
}
if err = report.User(&report.UserInfo{
Mid: dm.Mid,
Business: _businessUserLogDm,
Type: userLogType,
Oid: dm.ID,
Action: userLogAction,
Ctime: time.Now(),
Platform: fmt.Sprint(dm.Content.Plat),
IP: remoteIP,
Index: []interface{}{dm.Oid},
Content: map[string]interface{}{
"ip": remoteIP,
"port": remoteAddr,
"msg": msg,
},
}); err != nil {
log.Error("reportUserLog(dmid:%v) error(%v)", dm.ID, err)
return
}
return
}

View File

@@ -0,0 +1,56 @@
package dao
import (
"context"
"go-common/app/interface/main/dm2/model"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoReportDmGarbageLog(t *testing.T) {
convey.Convey("ReportDmGarbageLog", t, func(ctx convey.C) {
var (
c = context.Background()
dm = &model.DM{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.ReportDmGarbageLog(c, dm)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoReportDmLog(t *testing.T) {
convey.Convey("ReportDmLog", t, func(ctx convey.C) {
var (
c = context.Background()
dm = &model.DM{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.ReportDmLog(c, dm)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoreportUserLog(t *testing.T) {
convey.Convey("reportUserLog", t, func(ctx convey.C) {
var (
c = context.Background()
dm = &model.DM{}
userLogType = int(0)
userLogAction = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := testDao.reportUserLog(c, dm, userLogType, userLogAction)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,83 @@
package dao
import (
"context"
"net/url"
"strconv"
"go-common/app/interface/main/dm2/model"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
)
const (
_workFlowTagList = "/x/internal/workflow/tag/v3/list"
_workFlowAppealAdd = "/x/internal/workflow/appeal/v3/add"
_workFlowAppealDelete = "/x/internal/workflow/appeal/v3/delete"
)
// WorkFlowTagList get tag list from workflow
func (d *Dao) WorkFlowTagList(c context.Context, bid, rid int64) (data []*model.WorkFlowTag, err error) {
var (
res *model.WorkFlowTagListResp
params = url.Values{}
uri = d.conf.Host.API + _workFlowTagList
ip = metadata.String(c, metadata.RemoteIP)
)
params.Set("bid", strconv.FormatInt(bid, 10))
params.Set("rid", strconv.FormatInt(rid, 10))
if err = d.httpCli.Get(c, uri, 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
}
data = res.Data
err = nil
return
}
// WorkFlowAppealAdd add a record to workflow
func (d *Dao) WorkFlowAppealAdd(c context.Context, req *model.WorkFlowAppealAddReq) (err error) {
var (
res *model.CommonResponse
uri = d.conf.Host.API + _workFlowAppealAdd
ip = metadata.String(c, metadata.RemoteIP)
)
if err = d.httpCli.Post(c, uri, ip, req.Params(), &res); err != nil {
log.Error("WorkFlowAppealAdd(req:%+v),error(%v)", req.Params(), err)
return
}
if err = ecode.Int(res.Code); err != ecode.OK {
log.Error("WorkFlowAppealAdd(req:%+v),error(%v)", req, err)
return
}
err = nil
return
}
// WorkFlowAppealDelete .
func (d *Dao) WorkFlowAppealDelete(c context.Context, bid, oid, subtitleID int64) (err error) {
var (
res *model.CommonResponse
params = url.Values{}
uri = d.conf.Host.API + _workFlowAppealDelete
ip = metadata.String(c, metadata.RemoteIP)
)
params.Set("business", strconv.FormatInt(bid, 10))
params.Set("oid", strconv.FormatInt(oid, 10))
params.Set("eid", strconv.FormatInt(subtitleID, 10))
if err = d.httpCli.Post(c, uri, ip, params, &res); err != nil {
log.Error("WorkFlowAppealDelete(params:%v),error(%v)", params, err)
return
}
if err = ecode.Int(res.Code); err != ecode.OK {
log.Error("WorkFlowAppealDelete(params:%v),error(%v)", params, err)
return
}
err = nil
return
}

View File

@@ -0,0 +1,48 @@
package dao
import (
"context"
"go-common/app/interface/main/dm2/model"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoWorkFlowTagList(t *testing.T) {
convey.Convey("WorkFlowTagList", t, func(ctx convey.C) {
var (
c = context.Background()
bid = int64(0)
rid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.WorkFlowTagList(c, bid, rid)
})
})
}
func TestDaoWorkFlowAppealAdd(t *testing.T) {
convey.Convey("WorkFlowAppealAdd", t, func(ctx convey.C) {
var (
c = context.Background()
req = &model.WorkFlowAppealAddReq{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
testDao.WorkFlowAppealAdd(c, req)
})
})
}
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,66 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["http_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = ["//app/interface/main/dm2/model:go_default_library"],
)
go_library(
name = "go_default_library",
srcs = [
"dm.go",
"filter.go",
"history.go",
"http.go",
"manage.go",
"mask.go",
"member.go",
"subtitle.go",
"thumbup.go",
"view.go",
],
importpath = "go-common/app/interface/main/dm2/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/dm2/conf:go_default_library",
"//app/interface/main/dm2/model:go_default_library",
"//app/interface/main/dm2/model/oplog:go_default_library",
"//app/interface/main/dm2/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/antispam:go_default_library",
"//library/net/http/blademaster/middleware/auth:go_default_library",
"//library/net/http/blademaster/middleware/verify:go_default_library",
"//library/net/ip:go_default_library",
"//library/net/metadata:go_default_library",
"//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"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,365 @@
package http
import (
"math"
"net/http"
"strconv"
xtime "time"
"go-common/app/interface/main/dm2/model"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/ip"
"go-common/library/net/metadata"
"go-common/library/time"
)
func httpCode(err error) (code int) {
switch err {
case ecode.NotModified:
code = http.StatusNotModified
case ecode.RequestErr:
code = http.StatusBadRequest
case ecode.NothingFound:
code = http.StatusNotFound
case ecode.ServiceUnavailable:
code = http.StatusServiceUnavailable
default:
code = http.StatusInternalServerError
}
return
}
func dmXML(c *bm.Context) {
var (
p = c.Request.Form
comp = p.Get("comp")
contentType = "text/xml"
)
oid, err := strconv.ParseInt(p.Get("oid"), 10, 64)
if err != nil || oid <= 0 {
c.AbortWithStatus(http.StatusBadRequest)
return
}
data, err := dmSvc.DMXML(c, model.SubTypeVideo, oid)
if err != nil {
c.AbortWithStatus(httpCode(err))
log.Error("dmSvc.XML(%d) error(%v)", oid, err)
return
}
c.Writer.Header().Set("Content-Encoding", "deflate")
c.Writer.Header().Set("Last-Modified", xtime.Now().Format(http.TimeFormat))
if comp == "0" {
c.Writer.Header().Set("Content-Encoding", "none")
if data, err = dmSvc.Gzdeflate(data); err != nil {
log.Error("dmSvc.Gzdeflate(%d) error(%v)", oid, err)
c.AbortWithStatus(httpCode(err))
return
}
}
c.Bytes(http.StatusOK, contentType, data)
}
func dmSeg(c *bm.Context) {
var (
plat int32
mid int64
contentType = "application/octet-stream"
p = c.Request.Form
)
iMid, ok := c.Get("mid")
if ok {
mid = iMid.(int64)
}
oid, err := strconv.ParseInt(p.Get("oid"), 10, 64)
if err != nil || oid <= 0 {
c.AbortWithStatus(http.StatusBadRequest)
return
}
ps, err := strconv.ParseInt(p.Get("ps"), 10, 64)
if err != nil {
c.AbortWithStatus(http.StatusBadRequest)
return
}
tp, err := strconv.ParseInt(p.Get("type"), 10, 64)
if err != nil {
c.AbortWithStatus(http.StatusBadRequest)
return
}
aid, err := strconv.ParseInt(p.Get("aid"), 10, 64)
if err != nil {
c.AbortWithStatus(http.StatusBadRequest)
return
}
platform, err := strconv.ParseInt(p.Get("plat"), 10, 64)
if err != nil {
plat = model.PlatUnknow
} else {
plat = int32(platform)
}
data, err := dmSvc.DMSeg(c, int32(tp), plat, mid, aid, oid, ps)
if err != nil {
c.AbortWithStatus(httpCode(err))
return
}
if len(data) == 0 {
c.AbortWithStatus(http.StatusNotFound)
return
}
c.Bytes(http.StatusOK, contentType, data)
}
func dmSegV2(c *bm.Context) {
var (
plat int32
mid int64
p = c.Request.Form
)
iMid, ok := c.Get("mid")
if ok {
mid = iMid.(int64)
}
oid, err := strconv.ParseInt(p.Get("oid"), 10, 64)
if err != nil || oid <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
pn, err := strconv.ParseInt(p.Get("pn"), 10, 64)
if err != nil || pn <= 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
}
aid, err := strconv.ParseInt(p.Get("aid"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
platform, err := strconv.ParseInt(p.Get("plat"), 10, 64)
if err != nil {
plat = model.PlatUnknow
} else {
plat = int32(platform)
}
c.JSON(dmSvc.DMSegV2(c, int32(tp), mid, aid, oid, pn, plat))
}
func dm(c *bm.Context) {
p := c.Request.Form
oid, err := strconv.ParseInt(p.Get("oid"), 10, 64)
if err != nil || oid <= 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
}
aid, err := strconv.ParseInt(p.Get("aid"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
c.JSON(dmSvc.DM(c, int32(tp), aid, oid))
}
func ajaxDM(c *bm.Context) {
var (
p = c.Request.Form
msgs = make([]string, 0)
)
app := p.Get("mobi_app")
if app == "android" || app == "iphone" {
c.JSON(msgs, nil)
return
}
aid, err := strconv.ParseInt(p.Get("aid"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
c.JSON(dmSvc.AjaxDM(c, aid))
}
// validDMStyle 验证弾幕pool and mode.
func validDMStyle(pool, mode int32) (valid bool) {
switch pool {
case model.PoolNormal, model.PoolSubtitle:
if mode == model.ModeRolling || mode == model.ModeBottom || mode == model.ModeTop ||
mode == model.ModeReverse || mode == model.ModeSpecial {
valid = true
}
case model.PoolSpecial:
if mode == model.ModeCode || mode == model.ModeBAS {
valid = true
}
}
return
}
//dm post
func dmPost(c *bm.Context) {
var (
plat = int64(model.PlatUnknow)
p = c.Request.Form
now = xtime.Now().Unix()
)
mid, _ := c.Get("mid")
msg := p.Get("msg")
typ, err := strconv.ParseInt(p.Get("type"), 10, 64)
if err != nil || int32(typ) != model.SubTypeVideo {
c.JSON(nil, ecode.RequestErr)
return
}
aid, err := strconv.ParseInt(p.Get("aid"), 10, 64)
if err != nil || aid <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
oid, err := strconv.ParseInt(p.Get("oid"), 10, 64)
if err != nil || oid <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
progress, err := strconv.ParseInt(p.Get("progress"), 10, 32) // NOTE 老接口过来的弹幕时间为秒
if err != nil || progress < 0 || progress > math.MaxInt32 {
c.JSON(nil, ecode.RequestErr)
return
}
color, err := strconv.ParseInt(p.Get("color"), 10, 64)
if err != nil || color < 0 || color > math.MaxInt32 {
c.JSON(nil, ecode.RequestErr)
return
}
fontsize, err := strconv.ParseInt(p.Get("fontsize"), 10, 32)
if err != nil || fontsize <= 0 || fontsize > 127 {
c.JSON(nil, ecode.RequestErr)
return
}
pool, err := strconv.ParseInt(p.Get("pool"), 10, 32)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
mode, err := strconv.ParseInt(p.Get("mode"), 10, 32)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if !validDMStyle(int32(pool), int32(mode)) {
c.JSON(nil, ecode.RequestErr)
return
}
rnd, err := strconv.ParseInt(p.Get("rnd"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
platStr := p.Get("plat")
if platStr != "" {
if plat, err = strconv.ParseInt(platStr, 10, 32); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
dm := &model.DM{
Type: int32(typ),
Oid: oid,
Mid: mid.(int64),
Progress: int32(progress),
Pool: int32(pool),
State: model.StateNormal,
Ctime: time.Time(now),
Mtime: time.Time(now),
Content: &model.Content{
FontSize: int32(fontsize),
Color: color,
IP: int64(ip.InetAtoN(metadata.String(c, metadata.RemoteIP))),
Mode: int32(mode),
Plat: int32(plat),
Msg: msg,
Ctime: time.Time(now),
Mtime: time.Time(now),
},
}
if dm.Pool == model.PoolSpecial {
dm.ContentSpe = &model.ContentSpecial{
Msg: msg,
Ctime: time.Time(now),
Mtime: time.Time(now),
}
}
if err = dmSvc.Post(c, dm, aid, rnd); err != nil {
c.JSON(nil, err)
return
}
data := map[string]interface{}{
"dmid": dm.ID,
}
c.JSON(data, nil)
}
// judgeDM dm judge list.
func judgeDM(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
}
data, err := dmSvc.JudgeDms(c, 1, cid, dmid)
if err != nil {
log.Error("dmSvc.JudgeDms(cid:%d,dmid:%d) error(%v)", cid, dmid, err)
c.JSON(nil, err)
return
}
c.JSON(data, nil)
}
func dmAdvert(c *bm.Context) {
p := c.Request.Form
arg := &model.ADReq{
ClientIP: metadata.String(c, metadata.RemoteIP),
Buvid: c.Request.Header.Get("Buvid"),
MobiApp: p.Get("mobi_app"),
ADExtra: p.Get("ad_extra"),
}
if mid, ok := c.Get("mid"); ok {
arg.Mid = mid.(int64)
}
typ, err := strconv.ParseInt(p.Get("type"), 10, 64)
if err != nil || int32(typ) != model.SubTypeVideo {
c.JSON(nil, ecode.RequestErr)
return
}
aid, err := strconv.ParseInt(p.Get("aid"), 10, 64)
if err != nil || aid <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
arg.Aid = aid
oid, err := strconv.ParseInt(p.Get("oid"), 10, 64)
if err != nil || oid <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
arg.Oid = oid
build, err := strconv.ParseInt(p.Get("build"), 10, 64)
if err != nil || build <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
arg.Build = build
c.JSON(dmSvc.DMAdvert(c, arg))
}

View File

@@ -0,0 +1,94 @@
package http
import (
"encoding/json"
"strconv"
"go-common/app/interface/main/dm2/model"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
)
func upFilters(c *bm.Context) {
mid, _ := c.Get("mid")
data, err := dmSvc.UpFilters(c, mid.(int64))
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(data, nil)
}
// 前端协管/up主禁言用户接口
func addUpFilterID(c *bm.Context) {
var (
p = c.Request.Form
fltList = make([]*model.UpFilter, 0)
fltMap = make(map[string]string)
)
mid, _ := c.Get("mid")
fType, err := strconv.ParseInt(p.Get("type"), 10, 64)
if err != nil || fType != int64(model.FilterTypeID) {
c.JSON(nil, ecode.RequestErr)
return
}
oid, err := strconv.ParseInt(p.Get("oid"), 10, 64)
if err != nil || oid <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if err = json.Unmarshal([]byte(p.Get("filters")), &fltList); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
for _, v := range fltList {
fltMap[v.Filter] = v.Comment
}
if err = dmSvc.AddUpFilterID(c, mid.(int64), oid, fltMap); err != nil {
c.JSON(nil, err)
return
}
c.JSON(nil, nil)
}
// 创作中心up主添加屏蔽词
func editUpFilters(c *bm.Context) {
var (
p = c.Request.Form
filters = make([]*model.UpFilter, 0)
fType int64
fltMap = make(map[string]string)
)
mid, _ := c.Get("mid")
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 = json.Unmarshal([]byte(p.Get("filters")), &filters); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if fType, err = strconv.ParseInt(p.Get("type"), 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
for _, filter := range filters {
fltMap[filter.Filter] = filter.Comment
}
switch int8(active) {
case model.FilterActive:
err = dmSvc.AddUpFilters(c, mid.(int64), int8(fType), fltMap)
case model.FilterUnActive:
flts := make([]string, 0)
for f := range fltMap {
flts = append(flts, f)
}
if _, err = dmSvc.EditUpFilters(c, mid.(int64), int8(fType), model.FilterUnActive, flts); err != nil {
break
}
default:
err = ecode.RequestErr
}
c.JSON(nil, err)
}

View File

@@ -0,0 +1,97 @@
package http
import (
"net/http"
"strconv"
"time"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
)
func dmHistory(c *bm.Context) {
var (
p = c.Request.Form
contextType = "text/xml"
)
tp, err := strconv.ParseInt(p.Get("type"), 10, 64)
if err != nil {
c.AbortWithStatus(http.StatusBadRequest)
return
}
oid, err := strconv.ParseInt(p.Get("oid"), 10, 64)
if err != nil {
c.AbortWithStatus(http.StatusBadRequest)
return
}
date, err := time.Parse("2006-01-02", p.Get("date"))
if err != nil {
c.AbortWithStatus(http.StatusBadRequest)
return
}
// convert 2006-01-02-->2016-01-02 23:59:59
tm := time.Date(date.Year(), date.Month(), date.Day(), 23, 59, 59, 0, time.Local)
data, err := dmSvc.SearchDMHistory(c, int32(tp), oid, tm.Unix())
if err != nil {
c.AbortWithStatus(httpCode(err))
return
}
c.Writer.Header().Set("Content-Encoding", "deflate")
c.Bytes(200, contextType, data)
}
func dmHistoryV2(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
}
date, err := time.Parse("2006-01-02", p.Get("date"))
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
// convert 2006-01-02-->2016-01-02 23:59:59
tm := time.Date(date.Year(), date.Month(), date.Day(), 23, 59, 59, 0, time.Local)
c.JSON(dmSvc.SearchDMHistoryV2(c, int32(tp), oid, tm.Unix()))
}
func dmHistoryIndex(c *bm.Context) {
var (
p = c.Request.Form
now = time.Now()
)
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
}
month := p.Get("month")
date, err := time.Parse("2006-01", month)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
// only allow recent one year query
if now.Year()-date.Year() >= 1 && now.Month()-date.Month() > 12 {
c.JSON(nil, ecode.RequestErr)
return
}
data, err := dmSvc.SearchDMHisIndex(c, int32(tp), oid, month)
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(data, nil)
}

View File

@@ -0,0 +1,112 @@
package http
import (
"net/http"
"go-common/app/interface/main/dm2/conf"
"go-common/app/interface/main/dm2/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/antispam"
"go-common/library/net/http/blademaster/middleware/auth"
"go-common/library/net/http/blademaster/middleware/verify"
)
var (
dmSvc *service.Service
antispamSvc *antispam.Antispam
authSvc *auth.Auth
verifySvc *verify.Verify
)
// Init http init.
func Init(c *conf.Config, s *service.Service) {
dmSvc = s
authSvc = auth.New(c.Auth)
verifySvc = verify.New(c.Verify)
antispamSvc = antispam.New(c.Antispam)
engine := bm.NewServer(c.HTTPServer)
engine.Use(bm.Recovery(), bm.Trace(), bm.Logger())
innerRouter(engine)
outerRouter(engine)
if err := engine.Start(); err != nil {
log.Error("engine.Start() error(%v)", err)
panic(err)
}
}
// innerRouter init router api path.
func innerRouter(e *bm.Engine) {
group := e.Group("/x/internal/v2/dm", bm.CSRF())
{
group.GET("/search", verifySvc.VerifyUser, dmUpSearch)
group.GET("/recent", verifySvc.VerifyUser, dmUpRecent)
group.GET("/distribution", verifySvc.Verify, dmDistribution)
group.POST("/edit/state", verifySvc.VerifyUser, editState)
group.POST("/edit/pool", verifySvc.VerifyUser, editPool)
group.POST("/mask/update", verifySvc.Verify, updateMask)
group.POST("/subtitle/lan/add", verifySvc.Verify, subtitleLanAdd)
group.POST("/subtitle/upos/callback", waveFormCallBack)
}
}
func outerRouter(e *bm.Engine) {
e.GET("/monitor/ping", ping)
e.GET("/x/v1/dm/list.so", dmXML)
group := e.Group("/x/v2/dm", bm.CSRF())
{
group.GET("/view", authSvc.Guest, view)
group.GET("", dm)
group.GET("/search", authSvc.User, dmUpSearch)
group.GET("/ajax", ajaxDM)
group.GET("/list.so", authSvc.Guest, dmSeg)
group.GET("/list", authSvc.Guest, dmSegV2)
group.GET("/judge/list", authSvc.Guest, judgeDM)
group.GET("/thumbup/stats", authSvc.Guest, thumbupStats)
group.GET("/history", authSvc.User, antispamSvc.ServeHTTP, dmHistory)
group.GET("/history/list", authSvc.User, antispamSvc.ServeHTTP, dmHistoryV2)
group.GET("/history/index", authSvc.User, antispamSvc.ServeHTTP, dmHistoryIndex)
group.POST("/thumbup/add", authSvc.User, thumbupDM)
group.POST("/post", authSvc.User, dmPost)
group.POST("/edit/state", authSvc.User, editState)
group.POST("/edit/pool", authSvc.User, editPool)
group.POST("/filter/up/add", authSvc.User, antispamSvc.ServeHTTP, addUpFilterID)
group.GET("/recent", authSvc.User, dmUpRecent)
group.GET("/upper/config", authSvc.User, dmUpConfig)
group.POST("/advance/config", authSvc.User, upAdvancePermit)
group.GET("/filter/up", authSvc.User, upFilters)
group.POST("/filter/up/edit", authSvc.User, editUpFilters)
group.GET("/advert", authSvc.Guest, dmAdvert)
subtitle := group.Group("/subtitle")
{
subtitle.GET("/lans", authSvc.User, subtitleLans)
subtitle.POST("/del", authSvc.User, subtitleDel)
subtitle.POST("/lock", authSvc.User, subtitleLock)
subtitle.POST("/sign", authSvc.User, subtitleSign)
subtitle.GET("/show", authSvc.User, subtitleShow)
subtitle.GET("/archive/name", authSvc.User, subtitleArchiveName)
subtitle.POST("/draft/save", authSvc.User, draftSave)
subtitle.POST("/assit/audit", authSvc.User, assitAudit)
subtitle.GET("/permission", authSvc.User, subtitlePermission)
subtitle.GET("/waveform", authSvc.User, waveForm)
subtitle.POST("/filter", authSvc.User, subtitleFilter)
subtitle.GET("/report/tag", authSvc.User, subtitleReportTag)
subtitle.POST("/report/add", authSvc.User, subtitleReportAdd)
subtitle.GET("/search/assist", authSvc.User, searchAssist)
subtitle.GET("/search/author/list", authSvc.User, authorList)
}
}
}
// ping check server ok.
func ping(c *bm.Context) {
if err := dmSvc.Ping(c); err != nil {
log.Error("dm2 service ping error(%v)", err)
c.AbortWithStatus(http.StatusServiceUnavailable)
}
}

View File

@@ -0,0 +1,306 @@
package http
import (
"crypto/md5"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strconv"
"strings"
"testing"
"time"
"go-common/app/interface/main/dm2/model"
)
const (
_host = "http://127.0.0.1:6701"
_host2 = "http://api.bilibili.com"
_host3 = "http://uat-api.bilibili.co"
)
var (
cookie = `sid=88dol9eo; fts=1508407962; LIVE_BUVID=AUTO4115084079913953; UM_distinctid=15f3436b684ab-08804fe751374a-31657c00-1fa400-15f3436b685298; pgv_pvi=3618563072; rpdid=kmilkmximpdoswqploqxw; biliMzIsnew=1; biliMzTs=null; buvid3=CBB97852-6CF6-4D3A-B97F-5A9AD1D5827F26561infoc; finger=14bc3c4e; pgv_si=s6534896640; purl_token=bilibili_1511162275; DedeUserID=3078992; DedeUserID__ckMd5=55845496fd6119b5; SESSDATA=7bf20cf0%2C1513762568%2C258e3d17; bili_jct=160db0def61324719de104b7bfe1e3ef; _cnt_pm=0; _cnt_notify=0; _dfcaptcha=b5463dc96d22c22164a8c0e5a1ba9e96; member_v2=1`
dmLikeActURL = _host2 + "/x/v2/dm/thumbup/add"
dmLikeListURL = _host2 + "/x/v2/dm/thumbup/stats"
dmEditURL = _host + "/x/internal/v2/dm/edit/state"
dmPoolURL = _host + "/x/internal/v2/dm/edit/pool"
dmUpSearchURL = _host3 + "/x/v2/dm/search"
dmRecentURL = _host + "/x/internal/v2/dm/recent"
updateMaskURL = _host3 + "/x/internal/v2/dm/mask/update"
editUpFiltersURL = _host + "/x/v2/dm/filter/up/edit"
)
func TestEditUpFilter(t *testing.T) {
fliters := model.UpFilter{
Filter: "zzzzzz",
Comment: "",
}
p := url.Values{}
p.Set("active", "1")
p.Set("type", "0")
filter, err := json.Marshal(fliters)
if err != nil {
return
}
fmt.Print(string(filter))
p.Set("filters", string(filter))
mh := md5.Sum([]byte(p.Encode() + "3cf6bd1b0ff671021da5f424fea4b04a"))
p.Set("sign", hex.EncodeToString(mh[:]))
reqURL := editUpFiltersURL + "?" + p.Encode()
fmt.Println(reqURL)
body, err := opost(reqURL)
if err != nil {
t.Errorf("url(%s) error(%s)", reqURL, err)
t.FailNow()
}
if err = ccode(body); err != nil {
t.Fatal(err, string(body))
t.FailNow()
}
fmt.Println(string(body))
}
func TestRecent(t *testing.T) {
params := url.Values{}
params.Set("uid", "27515256")
params.Set("page", "5")
//params.Set("mid", "27515313")
params.Set("order", "ctime")
params.Set("size", "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 := dmRecentURL + "?" + 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()
}
fmt.Println(string(body))
}
func TestDMEdit(t *testing.T) {
params := url.Values{}
params.Set("oid", "5")
params.Set("type", "1")
params.Set("mid", "27515313")
params.Set("dmids", "719149463")
params.Set("state", "0")
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 := dmEditURL + "?" + params.Encode()
body, err := opost(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 TestDMPool(t *testing.T) {
params := url.Values{}
params.Set("cid", "5")
params.Set("mid", "27515313")
params.Set("dmids", "719149463")
params.Set("pool", "2")
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 := dmPoolURL + "?" + params.Encode()
body, err := opost(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 TestLikeDM(t *testing.T) {
params := url.Values{}
params.Set("oid", "5")
params.Set("dmid", "719149462")
params.Set("op", "1")
reqURL := dmLikeActURL + "?" + params.Encode()
body, err := cpost(reqURL)
if err != nil {
t.Errorf("url(%s) error(%s)", reqURL, err)
t.FailNow()
}
if err = ccode(body); err != nil {
t.Fatal(err, string(body))
t.FailNow()
}
fmt.Println(string(body))
}
func TestUpdateMask(t *testing.T) {
params := url.Values{}
params.Set("cid", "10109227")
params.Set("time", "30")
params.Set("fps", "20")
params.Set("plat", "1")
params.Set("count", "20")
params.Set("list", "26777486_s0_0_1499")
params.Set("appkey", "8f62754d8d594e90")
params.Set("ts", strconv.FormatInt(1527564095, 10))
data := params.Encode()
if strings.IndexByte(data, '+') > -1 {
data = strings.Replace(data, "+", "%20", -1)
}
mh := md5.Sum([]byte(data + "test"))
params.Set("sign", hex.EncodeToString(mh[:]))
s := updateMaskURL + "?" + params.Encode()
body, err := opost(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 TestLikeList(t *testing.T) {
params := url.Values{}
params.Set("oid", "27139273")
params.Set("ids", "719149462,719149463")
reqURL := dmLikeListURL + "?" + params.Encode()
fmt.Println(reqURL)
body, err := cget(reqURL)
if err != nil {
t.Errorf("url(%s) error(%s)", reqURL, err)
t.FailNow()
}
if err = ccode(body); err != nil {
t.Fatal(err, string(body))
t.FailNow()
}
fmt.Println(string(body))
}
func TestDMUpSearch(t *testing.T) {
params := url.Values{}
params.Set("oid", "10131156")
params.Set("type", "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[:]))
reqURL := dmUpSearchURL + "?" + params.Encode()
fmt.Println(reqURL)
body, err := oget(reqURL)
if err != nil {
t.Errorf("url(%s) error(%s)", reqURL, err)
t.FailNow()
}
if err = ccode(body); err != nil {
t.Fatal(err, string(body))
t.FailNow()
}
t.Logf("======%+v", body)
fmt.Println(string(body))
}
// 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", cookie)
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
}
func cget(url string) (body []byte, err error) {
client := &http.Client{}
req, err := http.NewRequest("GET", 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", cookie)
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,116 @@
package http
import (
"strconv"
"go-common/app/interface/main/dm2/model"
"go-common/app/interface/main/dm2/model/oplog"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/xstr"
)
// editState edit dm state.
// 0:正常1:删除 2:保护 3:取消保护
func editState(c *bm.Context) {
var (
p = c.Request.Form
dmids = make([]int64, 0)
)
mid, _ := c.Get("mid")
oid, err := strconv.ParseInt(p.Get("oid"), 10, 64)
if err != nil {
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 {
c.JSON(nil, ecode.RequestErr)
return
}
ids, err := xstr.SplitInts(p.Get("dmids"))
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
for _, dmid := range ids {
if dmid == 0 {
log.Warn("dmid is zero")
continue
}
dmids = append(dmids, dmid)
}
if len(dmids) == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
switch state {
case 0, 1:
err = dmSvc.EditDMState(c, int32(tp), mid.(int64), oid, int32(state), dmids, oplog.SourceUp, oplog.OperatorUp)
if err != nil {
log.Error("dmSvc.EditDMState(mid:%d, oid:%d, state:%d, dmids:%v) error(%v)", mid.(int64), oid, state, dmids, err)
c.JSON(nil, err)
return
}
err = dmSvc.UptSearchDMState(c, dmids, oid, int32(state), int32(tp))
case 2, 3:
var (
affectIds []int64
)
attr := model.AttrYes
if state == 3 {
attr = model.AttrNo
}
affectIds, err = dmSvc.EditDMAttr(c, int32(tp), mid.(int64), oid, model.AttrProtect, attr, dmids, oplog.SourceUp, oplog.OperatorUp)
if err != nil {
log.Error("dmSvc.EditDMAttr(mid:%d, oid:%d, attr:%d, dmids:%v) error(%v)", mid.(int64), oid, attr, dmids, err)
c.JSON(nil, err)
return
}
if len(affectIds) > 0 {
err = dmSvc.UptSearchDMAttr(c, affectIds, oid, attr, int32(tp))
}
default:
err = ecode.RequestErr
}
c.JSON(nil, err)
}
func editPool(c *bm.Context) {
p := c.Request.Form
mid, _ := c.Get("mid")
oid, err := strconv.ParseInt(p.Get("oid"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
tp, err := strconv.ParseInt(p.Get("type"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
pool, err := strconv.ParseInt(p.Get("pool"), 10, 64)
if err != nil {
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
}
err = dmSvc.EditDMPool(c, int32(tp), mid.(int64), oid, int32(pool), dmids, oplog.SourceUp, oplog.OperatorUp)
if err != nil {
log.Error("dmSvc.EditDMStat(oid:%d dmids:%v) error(%v)", oid, dmids, err)
c.JSON(nil, err)
return
}
err = dmSvc.UptSearchDMPool(c, dmids, oid, int32(pool), int32(tp))
c.JSON(nil, err)
}

View File

@@ -0,0 +1,42 @@
package http
import (
"strconv"
"strings"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
)
func updateMask(c *bm.Context) {
p := c.Request.Form
var (
cid, plat, fps, maskTime int64
list string
err error
)
if cid, err = strconv.ParseInt(p.Get("cid"), 10, 64); err != nil || cid <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if plat, err = strconv.ParseInt(p.Get("plat"), 10, 64); err != nil || plat < 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if p.Get("time") != "" {
if maskTime, err = strconv.ParseInt(p.Get("time"), 10, 64); err != nil || maskTime < 0 {
c.JSON(nil, ecode.RequestErr)
return
}
}
if p.Get("fps") != "" {
fps, err = strconv.ParseInt(p.Get("fps"), 10, 64)
if err != nil || fps <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
}
list = strings.Replace(p.Get("list"), " ", "", -1)
err = dmSvc.UpdateMask(c, cid, maskTime, int32(fps), int8(plat), list)
c.JSON(nil, err)
}

View File

@@ -0,0 +1,149 @@
package http
import (
"strconv"
"go-common/app/interface/main/dm2/model"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
// dmUpSearch danmu content List by cid
func dmUpSearch(c *bm.Context) {
p := c.Request.Form
mid, _ := c.Get("mid")
params := &model.SearchDMParams{
Mids: p.Get("mids"),
Mode: p.Get("modes"),
Pool: p.Get("pool"),
ProgressFrom: model.CondIntNil,
ProgressTo: model.CondIntNil,
CtimeFrom: p.Get("ctime_from"),
CtimeTo: p.Get("ctime_to"),
Pn: 1,
Ps: 100,
Sort: "desc",
Order: "ctime",
Keyword: p.Get("keyword"),
Attrs: p.Get("attrs"),
State: "0,2,6",
}
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("pn") != "" {
if params.Pn, err = strconv.ParseInt(p.Get("pn"), 10, 64); err != nil {
log.Error("param err page number %s %v", p.Get("pn"), err)
c.JSON(nil, ecode.RequestErr)
return
}
}
if p.Get("ps") != "" {
if params.Ps, err = strconv.ParseInt(p.Get("ps"), 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("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
}
params.ProgressFrom = params.ProgressFrom * 1000
}
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
}
params.ProgressTo = params.ProgressTo * 1000
}
if p.Get("order") != "" {
params.Order = p.Get("order")
}
if p.Get("sort") != "" {
params.Sort = p.Get("sort")
}
data, err := dmSvc.DMUpSearch(c, mid.(int64), params)
c.JSON(data, err)
}
// dmUpRecent get dm list by mid fron redis
func dmUpRecent(c *bm.Context) {
var (
err error
v = new(struct {
Pn int64 `form:"pn" default:"1"`
Ps int64 `form:"ps" default:"100"`
})
)
if err = c.Bind(v); err != nil {
return
}
mid, _ := c.Get("mid")
c.JSON(dmSvc.DMUpRecent(c, mid.(int64), v.Pn, v.Ps))
}
// 统计一个每个时间段弹幕数
func dmDistribution(c *bm.Context) {
p := c.Request.Form
typ, 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
}
interval, err := strconv.ParseInt(p.Get("interval"), 10, 64)
if err != nil || interval <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
data, err := dmSvc.DMDistribution(c, int32(typ), oid, int32(interval))
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(data, nil)
}
func dmUpConfig(c *bm.Context) {
mid, _ := c.Get("mid")
advPermit, err := dmSvc.AdvancePermit(c, mid.(int64))
if err != nil {
c.JSON(nil, err)
return
}
data := map[string]interface{}{
"advance_permit": advPermit,
}
c.JSON(data, nil)
}
func upAdvancePermit(c *bm.Context) {
mid, _ := c.Get("mid")
p := c.Request.Form
permit, err := strconv.ParseInt(p.Get("advance_permit"), 10, 64)
if err != nil || int8(permit) > model.AdvPermitForbid {
c.JSON(nil, ecode.RequestErr)
return
}
c.JSON(nil, dmSvc.UpdateAdvancePermit(c, mid.(int64), int8(permit)))
}

View File

@@ -0,0 +1,267 @@
package http
import (
"strconv"
"go-common/app/interface/main/dm2/model"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
)
func subtitleLanAdd(c *bm.Context) {
var (
err error
v = new(struct {
Code uint8 `form:"code" validate:"required"`
Lan string `form:"lan" validate:"required"`
DocEn string `form:"doc_en" validate:"required"`
DocZh string `form:"doc_zh" validate:"required"`
IsDelete bool `form:"is_delete"`
})
)
if err = c.Bind(v); err != nil {
return
}
c.JSON(nil, dmSvc.SubtitleLanOp(c, v.Code, v.Lan, v.DocZh, v.DocEn, v.IsDelete))
}
func subtitleFilter(c *bm.Context) {
var (
err error
v = new(struct {
Words string `form:"words" validate:"required"`
})
)
if err = c.Bind(v); err != nil {
return
}
c.JSON(dmSvc.SubtitleFilter(c, v.Words))
}
func draftSave(c *bm.Context) {
var (
v = new(struct {
Oid int64 `form:"oid" validate:"required"`
Type int32 `form:"type" validate:"required"`
Aid int64 `form:"aid" validate:"required" `
Lan string `form:"lan" validate:"required"`
Submit bool `form:"submit"`
Sign bool `form:"sign"`
OriginSubtitleID int64 `form:"origin_subtitle_id"`
Data string `form:"data" validate:"required"`
})
)
mid, _ := c.Get("mid")
if err := c.Bind(v); err != nil {
return
}
c.JSON(dmSvc.SaveSubtitleDraft(c, v.Aid, v.Oid, v.Type, mid.(int64), v.Lan, v.Submit, v.Sign, v.OriginSubtitleID, []byte(v.Data)))
}
func assitAudit(c *bm.Context) {
var (
v = new(struct {
Oid int64 `form:"oid" validate:"required"`
SubtitleID int64 `form:"subtitle_id" validate:"required"`
Pass bool `form:"pass"`
RejectComment string `form:"reject_comment"`
})
)
mid, _ := c.Get("mid")
if err := c.Bind(v); err != nil {
return
}
c.JSON(nil, dmSvc.AuditSubtitle(c, v.Oid, v.SubtitleID, mid.(int64), v.Pass, v.RejectComment))
}
func subtitleDel(c *bm.Context) {
var (
v = new(struct {
Oid int64 `form:"oid" validate:"required"`
SubtitleID int64 `form:"subtitle_id" validate:"required"`
})
)
mid, _ := c.Get("mid")
if err := c.Bind(v); err != nil {
return
}
c.JSON(nil, dmSvc.DelSubtitle(c, v.Oid, v.SubtitleID, mid.(int64)))
}
// 锁定发布字幕
func subtitleLock(c *bm.Context) {
var (
v = new(struct {
Oid int64 `form:"oid" validate:"required"`
Type int32 `form:"type" validate:"required"`
SubtitleID int64 `form:"subtitle_id" validate:"required"`
Lock bool `form:"lock"`
})
)
mid, _ := c.Get("mid")
if err := c.Bind(v); err != nil {
return
}
c.JSON(nil, dmSvc.SubtitleLock(c, v.Oid, v.Type, mid.(int64), v.SubtitleID, v.Lock))
}
// 署名字幕
func subtitleSign(c *bm.Context) {
var (
v = new(struct {
Oid int64 `form:"oid" validate:"required"`
Type int32 `form:"type" validate:"required"`
SubtitleID int64 `form:"subtitle_id" validate:"required"`
Sign bool `form:"sign"`
})
)
mid, _ := c.Get("mid")
if err := c.Bind(v); err != nil {
return
}
c.JSON(nil, dmSvc.SubtitleSign(c, v.Oid, v.Type, mid.(int64), v.SubtitleID, v.Sign))
}
func subtitleArchiveName(c *bm.Context) {
var (
v = new(struct {
Aid int64 `form:"aid" validate:"required"`
})
)
if err := c.Bind(v); err != nil {
return
}
c.JSON(dmSvc.ArchiveName(c, v.Aid))
}
// 查看字幕内容
func subtitleShow(c *bm.Context) {
var (
v = new(struct {
Oid int64 `form:"oid" validate:"required"`
SubtitleID int64 `form:"subtitle_id" validate:"required"`
})
)
mid, _ := c.Get("mid")
if err := c.Bind(v); err != nil {
return
}
c.JSON(dmSvc.SubtitleShow(c, v.Oid, v.SubtitleID, mid.(int64)))
}
func subtitleLans(c *bm.Context) {
var (
v = new(struct {
Oid int64 `form:"oid" validate:"required"`
Type int32 `form:"type" validate:"required"`
})
)
mid, _ := c.Get("mid")
if err := c.Bind(v); err != nil {
return
}
c.JSON(dmSvc.SubtitleLans(c, v.Oid, v.Type, mid.(int64)))
}
func searchAssist(c *bm.Context) {
var (
v = new(struct {
Oid int64 `form:"oid"`
Type int32 `form:"type"`
Aid int64 `form:"aid"`
Status int32 `form:"status"`
Page int32 `form:"page"`
Size int32 `form:"size" validate:"max=100"`
})
)
mid, _ := c.Get("mid")
if err := c.Bind(v); err != nil {
return
}
c.JSON(dmSvc.SearchAssist(c, v.Aid, v.Oid, v.Type, mid.(int64), v.Status, v.Page, v.Size))
}
func authorList(c *bm.Context) {
var (
v = new(struct {
Status int32 `form:"status"`
Page int32 `form:"page"`
Size int32 `form:"size" validate:"max=100"`
})
)
mid, _ := c.Get("mid")
if err := c.Bind(v); err != nil {
return
}
c.JSON(dmSvc.SearchAuthor(c, mid.(int64), v.Status, v.Page, v.Size))
}
func subtitlePermission(c *bm.Context) {
var (
v = new(struct {
Aid int64 `form:"aid" validate:"required"`
Oid int64 `form:"oid" validate:"required"`
Type int32 `form:"type" validate:"required"`
})
)
mid, _ := c.Get("mid")
if err := c.Bind(v); err != nil {
return
}
c.JSON(nil, dmSvc.SubtitlePermission(c, v.Aid, v.Oid, v.Type, mid.(int64)))
}
// waveForm .
func waveForm(c *bm.Context) {
var (
err error
v = new(struct {
Aid int64 `form:"aid" validate:"required"`
Oid int64 `form:"oid" validate:"required"`
Type int32 `form:"type" validate:"required"`
})
)
mid, _ := c.Get("mid")
if err = c.Bind(v); err != nil {
return
}
c.JSON(dmSvc.WaveForm(c, v.Aid, v.Oid, v.Type, mid.(int64)))
}
// waveFormCallBack .
func waveFormCallBack(c *bm.Context) {
var (
oid int64
err error
v = new(struct {
OK int32 `json:"ok"`
Info string `json:"info"`
})
)
if err = c.BindWith(v, binding.JSON); err != nil {
return
}
if oid, err = strconv.ParseInt(c.Request.URL.Query().Get("oid"), 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
c.JSON(nil, dmSvc.WaveFormCallBack(c, oid, 1, v.OK, v.Info))
}
func subtitleReportAdd(c *bm.Context) {
var (
err error
v = new(model.SubtitleReportAddParam)
)
mid, _ := c.Get("mid")
if err = c.Bind(v); err != nil {
return
}
c.JSON(nil, dmSvc.SubtitleReportAdd(c, mid.(int64), v))
}
func subtitleReportTag(c *bm.Context) {
c.JSON(dmSvc.SubtitleReportList(c))
}

View File

@@ -0,0 +1,62 @@
package http
import (
"strconv"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/xstr"
)
func thumbupDM(c *bm.Context) {
p := c.Request.Form
mid, _ := c.Get("mid")
oid, err := strconv.ParseInt(p.Get("oid"), 10, 64)
if err != nil || oid <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
dmid, err := strconv.ParseInt(p.Get("dmid"), 10, 64)
if err != nil || dmid <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
op, err := strconv.ParseInt(p.Get("op"), 10, 64)
if err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if err = dmSvc.ThumbupDM(c, oid, dmid, mid.(int64), int8(op)); err != nil {
log.Error("dmSvc.ThumbupDM(oid:%d,dmid:%d) error(%v)", oid, dmid, err)
c.JSON(nil, err)
return
}
c.JSON(nil, nil)
}
func thumbupStats(c *bm.Context) {
var (
mid int64
p = c.Request.Form
)
oid, err := strconv.ParseInt(p.Get("oid"), 10, 64)
if err != nil || oid <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if midI, ok := c.Get("mid"); ok {
mid = midI.(int64)
}
dmids, err := xstr.SplitInts(p.Get("ids"))
if err != nil || len(dmids) == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
data, err := dmSvc.ThumbupList(c, oid, mid, dmids)
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(data, nil)
}

View File

@@ -0,0 +1,23 @@
package http
import bm "go-common/library/net/http/blademaster"
func view(c *bm.Context) {
var (
mid int64
v = new(struct {
Oid int64 `form:"oid" validate:"required"`
Type int32 `form:"type" validate:"required"`
Aid int64 `form:"aid"`
Plat int32 `form:"plat"`
})
)
iMid, ok := c.Get("mid")
if ok {
mid = iMid.(int64)
}
if err := c.Bind(v); err != nil {
return
}
c.JSON(dmSvc.View(c, mid, v.Aid, v.Oid, v.Type, v.Plat))
}

View File

@@ -0,0 +1,32 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"item.go",
"lexer.go",
"parser.go",
],
importpath = "go-common/app/interface/main/dm2/lib/xregex",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,23 @@
package xregex
/*
golang version regex parser
refer to: https://github.com/aristotle9/as3cc/tree/master/java-template/src/org/lala/lex/utils/parser
*/
type rangeItem struct {
from int64
to int64
value int64
}
type stateTransItem struct {
isDead bool
toStates []int64
transEdge []*rangeItem
}
type productionItem struct {
headerID int64
bodyLength int64
}

View File

@@ -0,0 +1,432 @@
package xregex
/*
golang version regex parser
refer to: https://github.com/aristotle9/as3cc/tree/master/java-template/src/org/lala/lex/utils/parser
*/
import (
"errors"
"fmt"
"strconv"
)
const (
_initial = "INITIAL"
_deadState = 0xFFFFFFFF
_maxValue = 0x7fffffffffffffff
)
var (
errEOF = errors.New("已经到达末尾")
)
// Lexer golang lexter
type lexer struct {
transTable []*stateTransItem
finalTable map[int64]int64
initialTable map[string]int64
inputTable []*rangeItem
start int64
oldStart int64
tokenName string
yyText interface{}
yy interface{}
ended bool
initialInput int64
initialState string
line int64
column int64
advanced bool
source string
}
func newLexer() (lx *lexer) {
lx = &lexer{}
lx.transTable = []*stateTransItem{
{false, []int64{0xFFFFFFFF, 0x3, 0x2, 0x1},
[]*rangeItem{{0, 32, 0}, {33, 33, 1},
{34, 34, 2}, {35, 35, 3}}},
{false,
[]int64{0xFFFFFFFF, 0xF, 0xE, 0xD, 0xC, 0xB, 0xA, 0x9, 0x8, 0x7, 0x6, 0x5,
0x4},
[]*rangeItem{{0, 0, 0}, {1, 1, 1},
{2, 2, 2}, {3, 3, 3}, {4, 4, 4},
{5, 5, 5}, {6, 6, 6}, {7, 7, 7},
{8, 28, 8}, {29, 29, 9}, {30, 30, 10},
{31, 31, 11}, {32, 32, 12},
{33, 35, 0}}},
{false, []int64{0xFFFFFFFF, 0xF, 0xE, 0xD, 0x8, 0x12, 0x11, 0x10},
[]*rangeItem{{0, 0, 0}, {1, 1, 1},
{2, 2, 2}, {3, 3, 3}, {4, 7, 4},
{8, 8, 5}, {9, 9, 6}, {10, 27, 4},
{28, 28, 7}, {29, 32, 4},
{33, 35, 0}}},
{false, []int64{0xFFFFFFFF, 0x16, 0x15, 0x14, 0x13},
[]*rangeItem{{0, 21, 0}, {22, 24, 1},
{25, 25, 2}, {26, 26, 3}, {27, 27, 4},
{28, 35, 0}}},
{true, nil, nil}, {true, nil, nil},
{true, nil, nil}, {true, nil, nil},
{true, nil, nil}, {true, nil, nil},
{true, nil, nil}, {true, nil, nil},
{true, nil, nil},
{false,
[]int64{0xFFFFFFFF, 0x1F, 0x17, 0xE, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x1E, 0x21,
0x20, 0x18},
[]*rangeItem{{0, 0, 0}, {1, 1, 1},
{2, 9, 2}, {10, 11, 3}, {12, 12, 4},
{13, 13, 5}, {14, 14, 6}, {15, 15, 7},
{16, 16, 8}, {17, 18, 2}, {19, 19, 9},
{20, 20, 10}, {21, 21, 11}, {22, 23, 2},
{24, 24, 12}, {25, 32, 2},
{33, 35, 0}}},
{true, nil, nil}, {true, nil, nil},
{true, nil, nil}, {true, nil, nil},
{true, nil, nil}, {true, nil, nil},
{false, []int64{0xFFFFFFFF, 0x14},
[]*rangeItem{{0, 25, 0}, {26, 26, 1},
{27, 35, 0}}},
{true, nil, nil},
{false, []int64{0xFFFFFFFF, 0x16},
[]*rangeItem{{0, 21, 0}, {22, 24, 1},
{25, 35, 0}}},
{true, nil, nil},
{false, []int64{0xFFFFFFFF, 0x22},
[]*rangeItem{{0, 22, 0}, {23, 24, 1},
{25, 35, 0}}},
{false, []int64{0xFFFFFFFF, 0x23},
[]*rangeItem{{0, 10, 0}, {11, 11, 1},
{12, 12, 0}, {13, 14, 1}, {15, 17, 0},
{18, 18, 1}, {19, 19, 0}, {20, 20, 1},
{21, 21, 0}, {22, 24, 1},
{25, 35, 0}}},
{false, []int64{0xFFFFFFFF, 0x24},
[]*rangeItem{{0, 10, 0}, {11, 11, 1},
{12, 12, 0}, {13, 14, 1}, {15, 17, 0},
{18, 18, 1}, {19, 19, 0}, {20, 20, 1},
{21, 21, 0}, {22, 24, 1},
{25, 35, 0}}},
{true, nil, nil}, {true, nil, nil},
{true, nil, nil}, {true, nil, nil},
{true, nil, nil}, {true, nil, nil},
{true, nil, nil},
{false, []int64{0xFFFFFFFF, 0x25},
[]*rangeItem{{0, 22, 0}, {23, 24, 1},
{25, 35, 0}}},
{false, []int64{0xFFFFFFFF, 0x26},
[]*rangeItem{{0, 10, 0}, {11, 11, 1},
{12, 12, 0}, {13, 14, 1}, {15, 17, 0},
{18, 18, 1}, {19, 19, 0}, {20, 20, 1},
{21, 21, 0}, {22, 24, 1},
{25, 35, 0}}},
{false, []int64{0xFFFFFFFF, 0x27},
[]*rangeItem{{0, 10, 0}, {11, 11, 1},
{12, 12, 0}, {13, 14, 1}, {15, 17, 0},
{18, 18, 1}, {19, 19, 0}, {20, 20, 1},
{21, 21, 0}, {22, 24, 1},
{25, 35, 0}}},
{true, nil, nil}, {true, nil, nil},
{false, []int64{0xFFFFFFFF, 0x28},
[]*rangeItem{{0, 10, 0}, {11, 11, 1},
{12, 12, 0}, {13, 14, 1}, {15, 17, 0},
{18, 18, 1}, {19, 19, 0}, {20, 20, 1},
{21, 21, 0}, {22, 24, 1},
{25, 35, 0}}},
{false, []int64{0xFFFFFFFF, 0x29},
[]*rangeItem{{0, 10, 0}, {11, 11, 1},
{12, 12, 0}, {13, 14, 1}, {15, 17, 0},
{18, 18, 1}, {19, 19, 0}, {20, 20, 1},
{21, 21, 0}, {22, 24, 1},
{25, 35, 0}}},
{true, nil, nil}}
lx.finalTable = make(map[int64]int64)
lx.finalTable[0x4] = 0x0
lx.finalTable[0x5] = 0x4
lx.finalTable[0x6] = 0x1
lx.finalTable[0x7] = 0x2
lx.finalTable[0x8] = 0x1C
lx.finalTable[0x9] = 0x3
lx.finalTable[0xA] = 0x6
lx.finalTable[0xB] = 0x5
lx.finalTable[0xC] = 0xA
lx.finalTable[0xD] = 0x1C
lx.finalTable[0xE] = 0x12
lx.finalTable[0xF] = 0x1B
lx.finalTable[0x10] = 0x8
lx.finalTable[0x11] = 0x7
lx.finalTable[0x12] = 0x9
lx.finalTable[0x13] = 0xE
lx.finalTable[0x14] = 0xD
lx.finalTable[0x15] = 0xB
lx.finalTable[0x16] = 0xC
lx.finalTable[0x17] = 0x1A
lx.finalTable[0x18] = 0x1A
lx.finalTable[0x19] = 0x1A
lx.finalTable[0x1A] = 0x1A
lx.finalTable[0x1B] = 0x16
lx.finalTable[0x1C] = 0x17
lx.finalTable[0x1D] = 0x13
lx.finalTable[0x1E] = 0x15
lx.finalTable[0x1F] = 0x18
lx.finalTable[0x20] = 0x14
lx.finalTable[0x21] = 0x19
lx.finalTable[0x25] = 0xF
lx.finalTable[0x26] = 0x10
lx.finalTable[0x29] = 0x11
lx.inputTable = []*rangeItem{{0, 8, 17}, {9, 9, 26},
{10, 10, 0}, {11, 12, 17}, {13, 13, 0},
{14, 31, 17}, {32, 32, 26}, {33, 39, 17},
{40, 40, 31}, {41, 41, 5}, {42, 42, 32},
{43, 43, 30}, {44, 44, 25}, {45, 45, 28},
{46, 46, 2}, {47, 47, 1}, {48, 48, 24},
{49, 55, 23}, {56, 57, 22}, {58, 62, 17},
{63, 63, 29}, {64, 64, 17}, {65, 70, 18},
{71, 90, 17}, {91, 91, 6}, {92, 92, 3},
{93, 93, 8}, {94, 94, 9}, {95, 96, 17},
{97, 97, 18}, {98, 98, 14}, {99, 99, 20},
{100, 100, 11}, {101, 101, 18}, {102, 102, 13},
{103, 109, 17}, {110, 110, 21}, {111, 113, 17},
{114, 114, 12}, {115, 115, 10}, {116, 116, 19},
{117, 117, 15}, {118, 118, 17}, {119, 119, 10},
{120, 120, 16}, {121, 122, 17}, {123, 123, 4},
{124, 124, 7}, {125, 125, 27}, {126, 65535, 17}}
lx.initialTable = make(map[string]int64)
lx.initialTable["REPEAT"] = 0x1
lx.initialTable["BRACKET"] = 0x2
lx.initialTable["INITIAL"] = 0x3
return
}
func (lx *lexer) setSource(src string) {
if src != "" {
lx.source = src
}
lx.ended = false
lx.start = 0
lx.oldStart = 0
lx.line = 1
lx.column = 0
lx.advanced = true
lx.tokenName = ""
lx.yy = nil
lx.initialState = _initial
lx.initialInput = lx.initialTable[lx.initialState]
}
func (lx *lexer) getToken() (string, error) {
var err error
if lx.advanced {
lx.tokenName, err = lx.next()
lx.advanced = false
}
return lx.tokenName, err
}
func (lx *lexer) getPositionInfo() string {
return fmt.Sprintf("row(%d) column(%d)", lx.line, lx.column)
}
func (lx *lexer) next() (ret string, err error) {
for {
var (
nextState int64
ch int64
och = _maxValue
next = lx.start
curState = lx.transTable[0].toStates[lx.initialInput]
lastFinalState = int64(_deadState)
lastFinalPosition = lx.start
)
for {
if next < int64(len(lx.source)) {
ch = int64(lx.source[next])
// 计算行、列的位置
if och != _maxValue {
if ch == 0x0d { // \r符号
lx.column = 0
lx.line++
} else if ch == 0x0a { // \n
if och != 0x0d { // != \r
lx.column = 0
lx.line++
}
} else {
lx.column++
}
}
och = int(ch)
if nextState, err = lx.trans(curState, ch); err != nil {
return
}
} else {
nextState = _deadState
}
//OK
if nextState == _deadState {
if lx.start == lastFinalPosition {
if lx.start == int64(len(lx.source)) {
if !lx.ended {
lx.ended = true
return "<$>", nil
}
return "", errEOF
}
return "", fmt.Errorf("意外的字符(line:%d,col:%d) of %s", lx.line, lx.column, lx.source)
}
lx.yyText = lx.source[lx.start:lastFinalPosition]
lx.oldStart = lx.start
lx.start = lastFinalPosition
fIndex := lx.finalTable[lastFinalState]
switch fIndex {
case 0x0:
return "*", nil
case 0x1:
return "+", nil
case 0x2:
return "?", nil
case 0x3:
return "|", nil
case 0x4:
return "(", nil
case 0x5:
return ")", nil
case 0x6:
if err = lx.begin("BRACKET"); err != nil {
return
}
return "[", nil
case 0x7:
return "^", nil
case 0x8:
return "-", nil
case 0x9:
if err = lx.begin("INITIAL"); err != nil {
return
}
return "]", nil
case 0xA:
if err = lx.begin("REPEAT"); err != nil {
return
}
return "{", nil
case 0xB:
return ",", nil
case 0xC:
if lx.yyText, err = strconv.ParseInt(lx.yyText.(string), 10, 64); err != nil {
return
}
return "d", nil
case 0xE:
if err = lx.begin("INITIAL"); err != nil {
return
}
return "}", nil
case 0xF:
var tmp int64
if tmp, err = strconv.ParseInt(lx.yyText.(string)[2:4], 8, 64); err != nil {
return
}
lx.yyText = string(tmp)
return "c", nil
case 0x10:
var tmp int64
if tmp, err = strconv.ParseInt(lx.yyText.(string)[2:4], 16, 64); err != nil {
return
}
lx.yyText = string(tmp)
return "c", nil
case 0x11:
var tmp int64
if tmp, err = strconv.ParseInt(lx.yyText.(string)[2:6], 16, 64); err != nil {
return
}
lx.yyText = string(tmp)
return "c", nil
case 0x12:
return "escc", nil
case 0x13:
lx.yyText = "\r"
return "c", nil
case 0x14:
lx.yyText = "\n"
return "c", nil
case 0x15:
lx.yyText = "\t"
return "c", nil
case 0x16:
lx.yyText = "\b"
return "c", nil
case 0x17:
lx.yyText = "\f"
return "c", nil
case 0x18:
lx.yyText = "/"
return "c", nil
case 0x19:
return "escc", nil
case 0x1A:
lx.yyText = lx.yyText.(string)[1:2]
return "c", nil
case 0x1B:
return "/", nil
case 0x1C:
return "c", nil
}
break
} else {
next++
if _, ok := lx.finalTable[nextState]; ok {
lastFinalState = nextState
lastFinalPosition = next
}
curState = nextState
}
}
}
}
func (lx *lexer) begin(state string) error {
return lx.setInitialState(state)
}
func (lx *lexer) setInitialState(state string) (err error) {
if _, ok := lx.initialTable[state]; !ok {
err = fmt.Errorf("未定义的初始状态:%s", state)
return
}
lx.initialState = state
lx.initialInput = lx.initialTable[state]
return
}
func (lx *lexer) trans(curState, ch int64) (int64, error) {
if ch < lx.inputTable[0].from || ch > lx.inputTable[len(lx.inputTable)-1].to {
return 0, fmt.Errorf("line:%d,column:%d 输入字符超出范围", lx.line, lx.column)
}
if lx.transTable[curState].isDead {
return _deadState, nil
}
pubInput := find(ch, lx.inputTable)
innerInput := find(pubInput, lx.transTable[curState].transEdge)
return lx.transTable[curState].toStates[innerInput], nil
}
func find(code int64, table []*rangeItem) int64 {
var (
max = len(table) - 1
min int
mid uint64
)
for {
mid = uint64(min+max) >> 1
if table[mid].from <= code {
if table[mid].to >= code {
return table[mid].value
}
min = int(mid) + 1
} else {
max = int(mid) - 1
}
}
}

View File

@@ -0,0 +1,708 @@
package xregex
/*
golang version regex parser
refer to: https://github.com/aristotle9/as3cc/tree/master/java-template/src/org/lala/lex/utils/parser
*/
import (
"container/list"
"fmt"
"strings"
)
// Parser golang regex parser
type Parser struct {
actionTable []map[int64]int64
gotoTable map[int64]map[int64]int64
prodList []*productionItem
inputTable map[string]int64
codes []interface{}
duplCount int64
num int64
flags string
flagsC string
}
// Info print parser info.
func (p *Parser) Info() (s string) {
s += fmt.Sprintf("actionTable len:%d,", len(p.actionTable))
s += fmt.Sprintf("prodList len:%d,", len(p.prodList))
s += fmt.Sprintf("inputTable len:%d,", len(p.inputTable))
s += fmt.Sprintf("codes len:%d\n", len(p.codes))
return
}
// New return regex parser instance.
func New() (p *Parser) {
p = &Parser{}
var tmp map[int64]int64
p.actionTable = make([]map[int64]int64, 0)
p.actionTable = append(p.actionTable, nil)
tmp = make(map[int64]int64)
tmp[0x20] = 0x4
tmp[0x21] = 0x18
tmp[0x4] = 0x2E
tmp[0x5] = 0x30
tmp[0x6] = 0x1
tmp[0x7] = 0x2
tmp[0x8] = 0x1C
tmp[0x2A] = 0x24
tmp[0x2B] = 0x20
tmp[0x24] = 0x1E
tmp[0x27] = 0x6
tmp[0x10] = 0x10
tmp[0x11] = 0x12
tmp[0x12] = 0x14
tmp[0x14] = 0x1A
tmp[0x15] = 0xE
tmp[0x16] = 0x8
tmp[0x17] = 0xC
tmp[0x1A] = 0x16
tmp[0x1D] = 0xA
tmp[0x2C] = 0x22
p.actionTable = append(p.actionTable, tmp)
tmp = make(map[int64]int64)
tmp[0x0] = 0x5
tmp[0x21] = 0x18
tmp[0x4] = 0x2E
tmp[0x5] = 0x30
tmp[0x2C] = 0x22
tmp[0x8] = 0x1C
tmp[0x9] = 0x2F
tmp[0x2A] = 0x24
tmp[0x2B] = 0x20
tmp[0x24] = 0x1E
tmp[0x10] = 0x10
tmp[0x11] = 0x12
tmp[0x12] = 0x14
tmp[0x14] = 0x1A
tmp[0x15] = 0xE
tmp[0x17] = 0xC
tmp[0x1A] = 0x16
tmp[0x1D] = 0xA
p.actionTable = append(p.actionTable, tmp)
tmp = make(map[int64]int64)
tmp[0x21] = 0x18
tmp[0x4] = 0x2E
tmp[0x5] = 0x30
tmp[0x7] = 0x21
tmp[0x8] = 0x1C
tmp[0x9] = 0x21
tmp[0xA] = 0x21
tmp[0x2B] = 0x20
tmp[0x24] = 0x1E
tmp[0x10] = 0x10
tmp[0x11] = 0x12
tmp[0x12] = 0x14
tmp[0x14] = 0x1A
tmp[0x15] = 0xE
tmp[0x17] = 0xC
tmp[0x1A] = 0x16
tmp[0x2A] = 0x24
tmp[0x1D] = 0xA
tmp[0x2C] = 0x22
p.actionTable = append(p.actionTable, tmp)
tmp = make(map[int64]int64)
tmp[0x0] = 0x7
tmp[0x1] = 0x7
tmp[0x2] = 0x7
tmp[0x4] = 0x2E
tmp[0x5] = 0x30
tmp[0x7] = 0x7
tmp[0x8] = 0x1C
tmp[0x9] = 0x7
tmp[0xA] = 0x7
tmp[0x2B] = 0x20
tmp[0x24] = 0x1E
tmp[0xF] = 0x7
tmp[0x10] = 0x10
tmp[0x11] = 0x12
tmp[0x12] = 0x14
tmp[0x14] = 0x1A
tmp[0x15] = 0xE
tmp[0x17] = 0xC
tmp[0x1A] = 0x16
tmp[0x2A] = 0x24
tmp[0x21] = 0x18
tmp[0x1D] = 0x7
tmp[0x2C] = 0x22
p.actionTable = append(p.actionTable, tmp)
tmp = make(map[int64]int64)
tmp[0x21] = 0x18
tmp[0x4] = 0x2E
tmp[0x5] = 0x30
tmp[0x2C] = 0x22
tmp[0x8] = 0x1C
tmp[0xA] = 0x31
tmp[0x2B] = 0x20
tmp[0x24] = 0x1E
tmp[0x10] = 0x10
tmp[0x11] = 0x12
tmp[0x12] = 0x14
tmp[0x14] = 0x1A
tmp[0x15] = 0xE
tmp[0x17] = 0xC
tmp[0x1A] = 0x16
tmp[0x2A] = 0x24
tmp[0x1D] = 0xA
p.actionTable = append(p.actionTable, tmp)
tmp = make(map[int64]int64)
tmp[0x21] = 0x18
tmp[0x4] = 0x2E
tmp[0x5] = 0x30
tmp[0x7] = 0x23
tmp[0x8] = 0x1C
tmp[0x9] = 0x23
tmp[0xA] = 0x23
tmp[0x2B] = 0x20
tmp[0x24] = 0x1E
tmp[0x10] = 0x10
tmp[0x11] = 0x12
tmp[0x12] = 0x14
tmp[0x14] = 0x23
tmp[0x15] = 0xE
tmp[0x17] = 0xC
tmp[0x1A] = 0x16
tmp[0x2A] = 0x24
tmp[0x1D] = 0x23
tmp[0x2C] = 0x22
p.actionTable = append(p.actionTable, tmp)
tmp = make(map[int64]int64)
tmp[0x21] = 0x18
tmp[0x4] = 0x2E
tmp[0x5] = 0x30
tmp[0x7] = 0x25
tmp[0x8] = 0x1C
tmp[0x9] = 0x25
tmp[0xA] = 0x25
tmp[0x2B] = 0x20
tmp[0x24] = 0x1E
tmp[0x10] = 0x10
tmp[0x11] = 0x12
tmp[0x12] = 0x14
tmp[0x14] = 0x25
tmp[0x15] = 0xE
tmp[0x17] = 0xC
tmp[0x1A] = 0x16
tmp[0x2A] = 0x24
tmp[0x1D] = 0x25
tmp[0x2C] = 0x22
p.actionTable = append(p.actionTable, tmp)
tmp = make(map[int64]int64)
tmp[0x21] = 0x18
tmp[0x4] = 0x2E
tmp[0x5] = 0x30
tmp[0x7] = 0x27
tmp[0x8] = 0x1C
tmp[0x9] = 0x27
tmp[0xA] = 0x27
tmp[0x2B] = 0x20
tmp[0x24] = 0x1E
tmp[0x10] = 0x10
tmp[0x11] = 0x12
tmp[0x12] = 0x14
tmp[0x14] = 0x27
tmp[0x15] = 0xE
tmp[0x17] = 0xC
tmp[0x1A] = 0x16
tmp[0x2A] = 0x24
tmp[0x1D] = 0x27
tmp[0x2C] = 0x22
p.actionTable = append(p.actionTable, tmp)
tmp = make(map[int64]int64)
tmp[0x0] = 0x9
tmp[0x1] = 0x9
tmp[0x2] = 0x9
tmp[0x4] = 0x2E
tmp[0x5] = 0x30
tmp[0x7] = 0x9
tmp[0x8] = 0x1C
tmp[0x9] = 0x9
tmp[0xA] = 0x9
tmp[0x2B] = 0x20
tmp[0x24] = 0x1E
tmp[0xF] = 0x9
tmp[0x10] = 0x10
tmp[0x11] = 0x12
tmp[0x12] = 0x14
tmp[0x14] = 0x1A
tmp[0x15] = 0xE
tmp[0x17] = 0xC
tmp[0x1A] = 0x16
tmp[0x2A] = 0x24
tmp[0x21] = 0x18
tmp[0x1D] = 0x9
tmp[0x2C] = 0x22
p.actionTable = append(p.actionTable, tmp)
tmp = make(map[int64]int64)
tmp[0x28] = 0x26
tmp[0x22] = 0x2C
tmp[0x1C] = 0x28
tmp[0x5] = 0x30
tmp[0x18] = 0x45
tmp[0x1B] = 0x2E
tmp[0xC] = 0x2E
tmp[0xD] = 0x2A
tmp[0xE] = 0x37
p.actionTable = append(p.actionTable, tmp)
tmp = make(map[int64]int64)
tmp[0x3] = 0x19
p.actionTable = append(p.actionTable, tmp)
tmp = make(map[int64]int64)
tmp[0x21] = 0x18
tmp[0x4] = 0x2E
tmp[0x5] = 0x30
tmp[0x7] = 0x29
tmp[0x8] = 0x1C
tmp[0x9] = 0x29
tmp[0xA] = 0x29
tmp[0x2B] = 0x20
tmp[0x24] = 0x1E
tmp[0x10] = 0x10
tmp[0x11] = 0x12
tmp[0x12] = 0x14
tmp[0x14] = 0x29
tmp[0x15] = 0xE
tmp[0x17] = 0xC
tmp[0x1A] = 0x16
tmp[0x2A] = 0x24
tmp[0x1D] = 0x29
tmp[0x2C] = 0x22
p.actionTable = append(p.actionTable, tmp)
tmp = make(map[int64]int64)
tmp[0x1F] = 0x4F
tmp[0x25] = 0x55
tmp[0x13] = 0x3F
p.actionTable = append(p.actionTable, tmp)
tmp = make(map[int64]int64)
tmp[0x29] = 0x5B
tmp[0x25] = 0x57
tmp[0x1E] = 0x4B
tmp[0x26] = 0x59
p.actionTable = append(p.actionTable, tmp)
tmp = make(map[int64]int64)
tmp[0x1E] = 0x4D
tmp[0x13] = 0x41
p.actionTable = append(p.actionTable, tmp)
tmp = make(map[int64]int64)
tmp[0x0] = 0xB
tmp[0x1] = 0xB
tmp[0x2] = 0xB
tmp[0x3] = 0x1B
tmp[0x4] = 0x2E
tmp[0x5] = 0x30
tmp[0x7] = 0xB
tmp[0x8] = 0x1C
tmp[0x9] = 0xB
tmp[0xA] = 0xB
tmp[0xB] = 0x1B
tmp[0xC] = 0x2E
tmp[0xD] = 0x2A
tmp[0xE] = 0x39
tmp[0xF] = 0xB
tmp[0x10] = 0x10
tmp[0x11] = 0x12
tmp[0x12] = 0x14
tmp[0x14] = 0x1A
tmp[0x15] = 0xE
tmp[0x16] = 0x8
tmp[0x17] = 0xC
tmp[0x18] = 0x39
tmp[0x19] = 0x47
tmp[0x1A] = 0x16
tmp[0x1B] = 0x2E
tmp[0x1C] = 0x28
tmp[0x1D] = 0xB
tmp[0x20] = 0xB
tmp[0x21] = 0x18
tmp[0x22] = 0x2C
tmp[0x23] = 0x53
tmp[0x24] = 0x1E
tmp[0x27] = 0x6
tmp[0x28] = 0x26
tmp[0x2A] = 0x24
tmp[0x2B] = 0x20
tmp[0x2C] = 0x22
p.actionTable = append(p.actionTable, tmp)
tmp = make(map[int64]int64)
tmp[0xC] = 0x35
tmp[0x1B] = 0x49
p.actionTable = append(p.actionTable, tmp)
tmp = make(map[int64]int64)
tmp[0x0] = 0xD
tmp[0x1] = 0xD
tmp[0x2] = 0xD
tmp[0x3] = 0xD
tmp[0x4] = 0x2E
tmp[0x5] = 0x30
tmp[0x7] = 0xD
tmp[0x8] = 0x1C
tmp[0x9] = 0xD
tmp[0xA] = 0xD
tmp[0xB] = 0xD
tmp[0xC] = 0x2E
tmp[0xD] = 0x2A
tmp[0xE] = 0xD
tmp[0xF] = 0xD
tmp[0x10] = 0x10
tmp[0x11] = 0x12
tmp[0x12] = 0x14
tmp[0x14] = 0x1A
tmp[0x15] = 0xE
tmp[0x16] = 0x8
tmp[0x17] = 0xC
tmp[0x18] = 0xD
tmp[0x1A] = 0x16
tmp[0x1B] = 0x2E
tmp[0x1C] = 0x28
tmp[0x1D] = 0xD
tmp[0x20] = 0xD
tmp[0x21] = 0x18
tmp[0x22] = 0x2C
tmp[0x24] = 0x1E
tmp[0x27] = 0x6
tmp[0x28] = 0x26
tmp[0x2A] = 0x24
tmp[0x2B] = 0x20
tmp[0x2C] = 0x22
p.actionTable = append(p.actionTable, tmp)
p.gotoTable = make(map[int64]map[int64]int64)
tmp = make(map[int64]int64)
tmp[0xB] = 0x33
tmp[0x3] = 0x1F
p.gotoTable[0x18] = tmp
tmp = make(map[int64]int64)
tmp[0x0] = 0xF
p.gotoTable[0x13] = tmp
tmp = make(map[int64]int64)
tmp[0x0] = 0x11
tmp[0x1] = 0x15
tmp[0x2] = 0x17
tmp[0x14] = 0x2B
tmp[0x7] = 0x2B
tmp[0x9] = 0x2B
tmp[0xA] = 0x2B
tmp[0x1D] = 0x2B
tmp[0xF] = 0x3D
p.gotoTable[0x14] = tmp
tmp = make(map[int64]int64)
tmp[0x16] = 0x43
p.gotoTable[0x15] = tmp
tmp = make(map[int64]int64)
tmp[0x0] = 0x13
tmp[0x1] = 0x13
tmp[0x2] = 0x13
tmp[0x3] = 0x1D
tmp[0x7] = 0x13
tmp[0x20] = 0x51
tmp[0x9] = 0x13
tmp[0xA] = 0x13
tmp[0xB] = 0x1D
tmp[0xE] = 0x3B
tmp[0xF] = 0x13
tmp[0x14] = 0x13
tmp[0x18] = 0x3B
tmp[0x1D] = 0x13
p.gotoTable[0x16] = tmp
tmp = make(map[int64]int64)
tmp[0x9] = 0x2D
tmp[0xA] = 0x2D
tmp[0x14] = 0x2D
tmp[0x1D] = 0x2D
tmp[0x7] = 0x2D
p.gotoTable[0x17] = tmp
p.prodList = []*productionItem{{0x19, 0x2}, {0x13, 0x1},
{0x13, 0x4}, {0x15, 0x2}, {0x15, 0x0},
{0x14, 0x3}, {0x14, 0x3}, {0x14, 0x2},
{0x14, 0x2}, {0x14, 0x2}, {0x14, 0x2},
{0x14, 0x3}, {0x14, 0x4}, {0x14, 0x2},
{0x14, 0x1}, {0x17, 0x3}, {0x17, 0x4},
{0x17, 0x5}, {0x17, 0x4}, {0x18, 0x4},
{0x18, 0x2}, {0x18, 0x1}, {0x18, 0x3},
{0x16, 0x1}, {0x16, 0x1}}
p.inputTable = make(map[string]int64)
p.inputTable["/"] = 0x2
p.inputTable["["] = 0x9
p.inputTable["escc"] = 0x12
p.inputTable["]"] = 0xA
p.inputTable["("] = 0x4
p.inputTable["{"] = 0xC
p.inputTable["^"] = 0xB
p.inputTable[")"] = 0x5
p.inputTable["|"] = 0x3
p.inputTable["?"] = 0x8
p.inputTable["}"] = 0xE
p.inputTable["+"] = 0x7
p.inputTable["*"] = 0x6
p.inputTable[","] = 0xF
p.inputTable["<$>"] = 0x1
p.inputTable["-"] = 0x11
p.inputTable["c"] = 0x10
p.inputTable["d"] = 0xD
return
}
func (p *Parser) put(data interface{}) error {
if fmt.Sprint(data) == "dupl" {
p.duplCount++
if p.duplCount > 100 {
return fmt.Errorf("dupl commands over 100")
}
}
return nil
}
func (p *Parser) parse(lx *lexer) (ret interface{}, err error) {
var (
act int64
token string
tokenID int64
state int64
actObj int64
stateStack = list.New()
outputStack []interface{}
)
stateStack.PushBack(uint(0))
for {
if token, err = lx.getToken(); err != nil {
return
}
tokenID = p.inputTable[token]
state = int64(stateStack.Front().Value.(uint))
actObj = p.actionTable[tokenID][state]
if actObj == 0 {
err = fmt.Errorf("Parse Error: %s", lx.getPositionInfo())
return
}
act = actObj
if act == 1 {
ret = outputStack[len(outputStack)-1]
return
} else if (act & 1) == 1 {
outputStack = append(outputStack, lx.yyText)
stateStack.PushFront(uint(act)>>1 - 1)
lx.advanced = true
} else if (act & 1) == 0 {
pi := uint(act) >> 1
length := p.prodList[pi].bodyLength
var result interface{}
if length > 0 {
result = outputStack[int64(len(outputStack))-length]
}
switch pi {
case 0x1:
result = p.codes
case 0x2:
result = p.codes
case 0x3:
p.flagsC = outputStack[len(outputStack)-1].(string)
if !strings.Contains(p.flags, p.flagsC) {
err = fmt.Errorf("Flag Repeated:%s", lx.getPositionInfo())
return
}
if !strings.Contains("igm", p.flagsC) {
err = fmt.Errorf("Unknow Flag:%s", lx.getPositionInfo())
return
}
p.flags += p.flagsC
case 0x4:
case 0x5:
if err = p.put("or"); err != nil {
return
}
case 0x6:
case 0x7:
case 0x8:
if err = p.put("star"); err != nil {
return
}
case 0x9:
if err = p.put("more"); err != nil {
return
}
case 0xA:
if err = p.put("ask"); err != nil {
return
}
case 0xB:
if err = p.put([]interface{}{"include", outputStack[len(outputStack)-2]}); err != nil {
return
}
case 0xC:
if err = p.put([]interface{}{"exclude", outputStack[len(outputStack)-2]}); err != nil {
return
}
case 0xD:
if err = p.put("cat"); err != nil {
return
}
case 0xE:
if err = p.put("single"); err != nil {
return
}
case 0xF:
p.num = (outputStack[len(outputStack)-2]).(int64) - 1
for p.num > 0 {
if err = p.put("dupl"); err != nil {
return
}
p.num--
}
p.num = (outputStack[len(outputStack)-2]).(int64) - 1
for p.num > 0 {
if err = p.put("cat"); err != nil {
return
}
p.num--
}
case 0x10:
if err = p.put("ask"); err != nil {
return
}
p.num = (outputStack[len(outputStack)-2]).(int64) - 1
for p.num > 0 {
if err = p.put("dupl"); err != nil {
return
}
p.num--
}
p.num = (outputStack[len(outputStack)-2]).(int64) - 1
for p.num > 0 {
if err = p.put("cat"); err != nil {
return
}
p.num--
}
case 0x11:
p.num = (outputStack[len(outputStack)-4]).(int64) - 1
for p.num > 0 {
if err = p.put("dupl"); err != nil {
return
}
p.num--
}
p.num = (outputStack[len(outputStack)-2]).(int64) - (outputStack[len(outputStack)-4]).(int64)
if p.num > 0 {
if err = p.put("dupl"); err != nil {
return
}
if err = p.put("ask"); err != nil {
return
}
for p.num > 1 {
if err = p.put("dupl"); err != nil {
return
}
p.num--
}
}
p.num = (outputStack[len(outputStack)-2]).(int64) - 1
for p.num > 0 {
if err = p.put("cat"); err != nil {
return
}
p.num--
}
case 0x12:
p.num = (outputStack[len(outputStack)-3]).(int64)
for p.num > 0 {
if err = p.put("dupl"); err != nil {
return
}
p.num--
}
if err = p.put("star"); err != nil {
return
}
p.num = (outputStack[len(outputStack)-3]).(int64)
for p.num > 0 {
if err = p.put("cat"); err != nil {
return
}
p.num--
}
case 0x13:
p.num = (outputStack[len(outputStack)-4]).(int64)
result = p.num + 1
if err = p.put([]interface{}{"c", (outputStack[len(outputStack)-3])}); err != nil {
return
}
if err = p.put([]interface{}{"c", (outputStack[len(outputStack)-1])}); err != nil {
return
}
if err = p.put("range"); err != nil {
return
}
case 0x14:
p.num = (outputStack[len(outputStack)-2]).(int64)
result = p.num + 1
if err = p.put("single"); err != nil {
return
}
case 0x15:
if err = p.put("single"); err != nil {
return
}
result = int64(1)
case 0x16:
if err = p.put([]interface{}{"c", (outputStack[len(outputStack)-3])}); err != nil {
return
}
if err = p.put([]interface{}{"c", (outputStack[len(outputStack)-1])}); err != nil {
return
}
if err = p.put("range"); err != nil {
return
}
result = int64(1)
case 0x17:
if err = p.put([]interface{}{"c", (outputStack[len(outputStack)-1])}); err != nil {
return
}
case 0x18:
if "\\c" == outputStack[len(outputStack)-1].(string) {
err = fmt.Errorf("Control Character:%s", lx.getPositionInfo())
return
}
if err = p.put([]interface{}{"escc", (outputStack[len(outputStack)-1])}); err != nil {
return
}
}
/** actions applying end **/
var j int64
var e *list.Element
for j < length {
e = stateStack.Front()
stateStack.Remove(e)
outputStack = outputStack[:len(outputStack)-1]
j++
}
state = int64(stateStack.Front().Value.(uint))
actObj = p.gotoTable[p.prodList[pi].headerID][state]
if actObj == 0 {
err = fmt.Errorf("goto error! %s", lx.getPositionInfo())
return
}
act = actObj
stateStack.PushFront(uint(act)>>1 - 1)
outputStack = append(outputStack, result)
}
}
}
// Parse parse input string.
func (p *Parser) Parse(source string) (result interface{}, err error) {
defer func() {
if e := recover(); e != nil {
err = fmt.Errorf("panic:%v", e)
return
}
}()
if source == "" {
return
}
lx := newLexer()
lx.setSource(source)
return p.parse(lx)
}

View File

@@ -0,0 +1,84 @@
load(
"@io_bazel_rules_go//proto:def.bzl",
"go_proto_library",
)
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
proto_library(
name = "model_proto",
srcs = ["dm.proto"],
tags = ["automanaged"],
deps = ["@gogo_special_proto//github.com/gogo/protobuf/gogoproto"],
)
go_proto_library(
name = "model_go_proto",
compilers = ["@io_bazel_rules_go//proto:gogofast_proto"],
importpath = "go-common/app/interface/main/dm2/model",
proto = ":model_proto",
tags = ["automanaged"],
deps = [
"//library/time:go_default_library",
"@com_github_gogo_protobuf//gogoproto:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"action.go",
"advance.go",
"advert.go",
"bangumi.go",
"dm.go",
"dm_seg.go",
"dm_special_location.go",
"filter.go",
"history.go",
"mask.go",
"member.go",
"params.go",
"rpc.go",
"subject.go",
"subtitle.go",
"thumbup.go",
"ugcpay.go",
"view.go",
"workflow.go",
],
embed = [":model_go_proto"],
importpath = "go-common/app/interface/main/dm2/model",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/dm2/model/oplog:go_default_library",
"//library/ecode:go_default_library",
"//library/time:go_default_library",
"//library/xstr:go_default_library",
"@com_github_gogo_protobuf//gogoproto:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/interface/main/dm2/model/oplog:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,44 @@
package model
import (
"encoding/json"
)
// Action actions sent to job
const (
ActionIdx = "idx"
ActionFlush = "flush"
ActAddDM = "dm_add" // 新增弹幕
ActFlushDMSeg = "dm_seg_flush" // 刷新分段弹幕缓存
)
// Action job msg.
type Action struct {
Action string `json:"action"`
Data json.RawMessage `json:"data"`
}
// JobParam job param.
type JobParam struct {
Type int32 `json:"type,omitempty"`
Pid int64 `json:"pid,omitempty"`
Oid int64 `json:"oid,omitempty"`
Cnt int64 `json:"cnt,omitempty"`
Num int64 `json:"num,omitempty"`
Duration int64 `json:"duration,omitempty"`
}
// Flush flush msg
type Flush struct {
Type int32 `json:"type,omitempty"`
Oid int64 `json:"oid,omitempty"`
Force bool `json:"force,omitempty"`
}
// ActionFlushDMSeg flush segment dm cache
type ActionFlushDMSeg struct {
Type int32 `json:"type"`
Oid int64 `json:"oid"`
Force bool `json:"force"`
Page *Page `json:"page"`
}

View File

@@ -0,0 +1,81 @@
package model
// all variable used in advance dm
const (
// mode
AdvSpeMode = "sp" // mode 7
AdvMode = "advance" // mode8 mode9
// type
AdvTypeRequest = "request"
AdvTypeAccept = "accept"
AdvTypeBuy = "buy"
AdvTypeDeny = "deny"
// coin
AdvSPCoin = 2
AdvCoin = 5
// reason
AdvSPCoinReason = "购买特殊弹幕"
AdvCoinReason = "购买高级弹幕"
AdvSPCoinCancelReason = "购买特殊弹幕被取消"
AdvCoinCancelReason = "购买高级弹幕被取消"
// confirm state
AdvStatConfirmDefault = 0
AdvStatConfirmAgree = 1
AdvStatConfirmRequest = 2
AdvStatConfirmDeny = 3
// 高级弹幕申请权限控制
AdvPermitAll = int8(0) // 任何人
AdvPermitFollower = int8(1) // 仅限粉丝
AdvPermitAttention = int8(2) // 仅限相互关注
AdvPermitForbid = int8(3) // 始终拒绝
)
// BuyAdv user buy adv
type BuyAdv struct {
CID int64
Owner int64
Mid int64
Type string
Timestamp int64
Mode string
Refund int
}
// ArgAdvBuy buy adv data
type ArgAdvBuy struct {
Mid int64
Owner int64
Type string
Reason string
Cid int64
Coin float64
Mode string
Cookie string
AccessKey string
Refund int
IsCoin bool
}
// AdvState state
type AdvState struct {
Coins int `json:"coins"`
Confirm int `json:"confirm"`
Accept bool `json:"accept"`
HasBuy bool `json:"hasBuy"`
}
// Advance dm_advancecomment
type Advance struct {
ID int64 `json:"id"`
Owner int64 `json:"owner"`
Cid int64 `json:"cid"`
Aid int64 `json:"aid"`
Type string `json:"type"`
Mode string `json:"mode"`
Mid int64 `json:"mid"`
Timestamp int64 `json:"timestamp"`
Refund int8 `json:"refund"`
Uname string `json:"uname"`
Title string `json:"title"`
Cover string `json:"cover"`
}

View File

@@ -0,0 +1,94 @@
package model
import (
"encoding/json"
"fmt"
)
// resource id defined by advert
const (
adRscIDIphone = 2630
adRscIDAndrod = 2631
adRscIDIphoneIcon = 2642
adRscIDAndroidIcon = 2643
)
// Resource get resource by mobi_app.
func Resource(mobiApp string) (rsc string) {
if mobiApp == "iphone" || mobiApp == "ipad" || mobiApp == "iphone_i" {
rsc = fmt.Sprintf("%d,%d", adRscIDIphone, adRscIDIphoneIcon)
} else {
rsc = fmt.Sprintf("%d,%d", adRscIDAndrod, adRscIDAndroidIcon)
}
return
}
// ADReq advert request params
type ADReq struct {
Aid int64 `json:"aid"`
Oid int64 `json:"oid"`
Mid int64 `json:"mid"`
Build int64 `json:"build"`
Buvid string `json:"buvid"`
ClientIP string `json:"ip"`
MobiApp string `json:"mobi_app"`
ADExtra string `json:"ad_extra"`
}
// ADResp advert response
type ADResp struct {
Icon *ADInfo `json:"icon,omitempty"`
ADs []*ADInfo `json:"ads_info,omitempty"`
}
// AD advert struct
type AD struct {
RequestID string `json:"request_id,omitempty"`
ADsInfo map[int64]map[int64]*ADInfo `json:"ads_info,omitempty"` // resource_id --> source_id --> adinfo
}
// ADInfo advert info.
type ADInfo struct {
// filed response from advert api
Index int `json:"index,omitempty"`
IsAd bool `json:"is_ad,omitempty"`
CmMark int `json:"cm_mark,omitempty"`
CardIndex int `json:"card_index,omitempty"`
ADInfo json.RawMessage `json:"ad_info,omitempty"`
// filed used in app
RequestID string `json:"request_id,omitempty"`
ResourceID int64 `json:"resource_id,omitempty"`
SourceID int64 `json:"source_id,omitempty"`
ClientIP string `json:"client_ip,omitempty"`
IsADLoc bool `json:"is_ad_loc,omitempty"`
}
// Convert convert AD to ADResp.
func (a *AD) Convert(clientIP string) (res *ADResp) {
res = new(ADResp)
for rscID, adInfoMap := range a.ADsInfo {
for srcID, adInfo := range adInfoMap {
v := new(ADInfo)
v.RequestID = a.RequestID
v.ResourceID = rscID
v.SourceID = srcID
v.ClientIP = clientIP
v.IsADLoc = true // 该字段服务端代码写死为true
if adInfo != nil {
v.Index = adInfo.Index
v.IsAd = adInfo.IsAd
v.CmMark = adInfo.CmMark
v.CardIndex = adInfo.CardIndex
}
if len(adInfo.ADInfo) > 0 {
v.ADInfo = adInfo.ADInfo
}
if v.ResourceID == adRscIDIphoneIcon || v.ResourceID == adRscIDAndroidIcon { // icon resouce id
res.Icon = v
continue
}
res.ADs = append(res.ADs, v)
}
}
return
}

View File

@@ -0,0 +1,24 @@
package model
import "encoding/json"
// Season 番剧季度对象
type Season struct {
AllowDownload string `json:"allow_download,omitempty"`
SeasonID string `json:"season_id"`
IsJump int `json:"is_jump"`
EpisodeStatus int `json:"episode_status"`
Title string `json:"title"`
Cover string `json:"cover"`
IsFinish string `json:"is_finish"`
IsStarted int `json:"is_started"`
NewestEpID string `json:"newest_ep_id"`
NewestEpIndex string `json:"newest_ep_index"`
TotalCount string `json:"total_count"`
Weekday string `json:"weekday"`
Evaluate string `json:"evaluate"`
Bp json.RawMessage `json:"rank,omitempty"`
UserSeason *struct {
Attention string `json:"attention"`
} `json:"user_season,omitempty"`
}

View File

@@ -0,0 +1,298 @@
package model
import (
"fmt"
"hash/crc32"
"strconv"
"go-common/library/time"
"go-common/library/xstr"
)
var (
bAmp = []byte(`&amp;`)
bGt = []byte(`&gt;`)
bLt = []byte(`&lt;`)
bSp = []byte(` `)
// LimitPerMin 每个rank权限允许的发送速度
LimitPerMin = map[int32]int64{
0: 10,
10000: 30,
15000: 30,
20000: 300,
25000: 60,
30000: 300,
32000: 300,
}
)
// All const variable used in dm2
const (
// <d p="播放时间弹幕模式字体大小颜色发送时间弹幕池用户hash弹幕id">弹幕内容</d>
_xmlFmt = `<d p="%.5f,%d,%d,%d,%d,%d,%s,%d">%s</d>`
// <d p="播放时间弹幕模式字体大小颜色发送时间弹幕池用户hash弹幕id用户id">弹幕内容</d>
_rnameFmt = `<d p="%.5f,%d,%d,%d,%d,%d,%s,%d,%d">%s</d>`
AttrNo = int32(0) // 属性位为0
AttrYes = int32(1) // 属性位为1
AttrProtect = uint(0) // 保护弹幕
StateNormal = int32(0) // 普通状态
StateDelete = int32(1) // 删除状态
StateHide = int32(2) // 隐藏状态
StateBlock = int32(3) // 屏蔽状态
StateFilter = int32(4) // 过滤状态
StateMonitorBefore = int32(5) // 先审后发
StateMonitorAfter = int32(6) // 先发后审
StateSystemFilter = int32(7) // 敏感词过滤
StateReportDelete = int32(8) // 举报删除
StateAdminDelete = int32(9) // 弹幕管理删除
StateUserDelete = int32(10) // 用户删除
StateScriptDelete = int32(11) // 举报脚本删除
StateTaskDel = int32(12) //弹幕任务删除
StateAiDelete = int32(13) // ai删除
PoolNormal = int32(0) // 普通弹幕池
PoolSubtitle = int32(1) // 字幕弹幕池
PoolSpecial = int32(2) // 特殊弹幕池
PlatUnknow = int32(0)
PlatWeb = int32(1)
PlatAndroid = int32(2)
PlatIPhone = int32(3)
PlatWpM = int32(4) // wp mobile
PlatIPad = int32(5)
PlatPadHd = int32(6) // ipad hd
PlatWpPc = int32(7) // win10
MaxLenDefMsg = 100
MaxLen7Msg = 300
// 弹幕模式
ModeRolling = int32(1)
ModeBottom = int32(4)
ModeTop = int32(5)
ModeReverse = int32(6)
ModeSpecial = int32(7)
ModeCode = int32(8)
ModeBAS = int32(9)
SpamBlack = 52001
SpamOverflow = 52002
SpamRestrict = 52005
)
// AdvanceCmt struct
type AdvanceCmt struct {
ID int64
Owner int64
Oid int64
Type string // request:申请中buy:已购买accept:已通过deny:拒绝
Mode string // 枚举类型sp:高级弹幕advance:pool2特殊弹幕
Timestamp int64
Mid int64
Refund int
}
// DailyLimiter daily limiter
type DailyLimiter struct {
Date string
Count int64
}
// Limiter retrun
type Limiter struct {
Allowance int64
Timestamp int64
}
// 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)
}
// DMSlice dm slice
type DMSlice []*DM
func (d DMSlice) Len() int { return len(d) }
func (d DMSlice) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
func (d DMSlice) Less(i, j int) bool { return d[i].ID < d[j].ID }
// DMSlice2 sort dm slice by progress
type DMSlice2 []*DM
func (d DMSlice2) Len() int { return len(d) }
func (d DMSlice2) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
func (d DMSlice2) Less(i, j int) bool { return d[i].Progress < d[j].Progress }
// JudgeDMList dm list of judge
type JudgeDMList struct {
List []*JDM `json:"list"`
Index []int64 `json:"index"`
}
// JDM judge dm
type JDM struct {
ID int64 `json:"id"`
Msg string `json:"msg"`
Mid int64 `json:"mid"`
Progress string `json:"progress"`
CTime time.Time `json:"ctime"`
}
// FilterData filter-service data
type FilterData struct {
Level int64 `json:"level"`
Limit int64 `json:"limit"`
Msg string `json:"msg"`
TypeID []int64 `json:"typeid"`
Hit []string `json:"hit"`
}
// ToXMLSpecialSeg .
func (d *DM) ToXMLSpecialSeg(realname bool) (s string) {
if d.Content == nil || d.Pool != PoolSpecial {
return
}
msg := d.Content.Msg
if d.ContentSpe != nil {
msg = d.ContentSpe.Msg
}
if len(msg) == 0 {
return
}
s = fmt.Sprintf(`<d id="%d">%s</d>`, d.ID, xmlReplace([]byte(msg)))
return
}
// ToXMLSeg convert dm struct to xml.
func (d *DM) ToXMLSeg(realname bool) (s string) {
if d.Content == nil {
return
}
msg := d.Content.Msg
if d.ContentSpe != nil {
msg = d.ContentSpe.Msg
}
if len(msg) == 0 {
return
}
if d.Pool == PoolSpecial {
msg = ""
}
if realname {
// <d p="弹幕ID,弹幕属性,播放时间,弹幕模式,字体大小,颜色,发送时间,弹幕池,用户hash id,用户mid">弹幕内容</d>
s = fmt.Sprintf(_xmlSegRealnameFmt, d.ID, d.Attr, d.Progress, d.Content.Mode, d.Content.FontSize, d.Content.Color, d.Ctime, d.Pool, Hash(d.Mid, uint32(d.Content.IP)), d.Mid, xmlReplace([]byte(msg)))
} else {
// <d p="弹幕ID,弹幕属性,播放时间,弹幕模式,字体大小,颜色,发送时间,弹幕池,用户id">弹幕内容</d>
s = fmt.Sprintf(_xmlSegFmt, d.ID, d.Attr, d.Progress, d.Content.Mode, d.Content.FontSize, d.Content.Color, d.Ctime, d.Pool, Hash(d.Mid, uint32(d.Content.IP)), xmlReplace([]byte(msg)))
}
return
}
// ToXML convert dm struct to xml.
func (d *DM) ToXML(realname bool) (s string) {
if d.Content == nil {
return
}
msg := d.Content.Msg
if d.ContentSpe != nil {
msg = d.ContentSpe.Msg
}
if len(msg) == 0 {
return
}
if realname {
// <d p="播放时间弹幕模式字体大小颜色发送时间弹幕池用户hash弹幕id用户id">弹幕内容</d>
s = fmt.Sprintf(_rnameFmt, float64(d.Progress)/1000.0, d.Content.Mode, d.Content.FontSize, d.Content.Color, d.Ctime, d.Pool, Hash(d.Mid, uint32(d.Content.IP)), d.ID, d.Mid, xmlReplace([]byte(msg)))
} else {
// <d p="播放时间弹幕模式字体大小颜色发送时间弹幕池用户hash弹幕id">弹幕内容</d>
s = fmt.Sprintf(_xmlFmt, float64(d.Progress)/1000.0, d.Content.Mode, d.Content.FontSize, d.Content.Color, d.Ctime, d.Pool, Hash(d.Mid, uint32(d.Content.IP)), d.ID, xmlReplace([]byte(msg)))
}
return
}
// xmlReplace replace special char in xml.
func xmlReplace(bi []byte) (bo []byte) {
for _, b := range bi {
if b == 0 {
continue
} else if b == '&' {
bo = append(bo, bAmp...)
continue
} else if b == '>' {
bo = append(bo, bGt...)
continue
} else if b == '<' {
bo = append(bo, bLt...)
continue
} else if (b >= 0x01 && b <= 0x08) || (b >= 0x0b && b <= 0x0c) || (b >= 0x0e && b <= 0x1f) || (b == 0x7f) {
// 替换掉控制字符,保留空格、回车、制表符
bo = append(bo, bSp...)
} else {
bo = append(bo, b)
}
}
return
}
// Hash return mid hash string.
func Hash(mid int64, ip uint32) string {
var s uint32
if mid != 0 {
s = crc32.ChecksumIEEE([]byte(strconv.FormatInt(mid, 10)))
return strconv.FormatInt(int64(s), 16)
}
s = crc32.ChecksumIEEE([]byte(strconv.FormatInt(int64(ip), 10)))
return "D" + strconv.FormatInt(int64(s), 16)
}
// IsDMVisible dm can visible
func IsDMVisible(state int32) bool {
if state == StateNormal || state == StateMonitorAfter {
return true
}
return false
}
// IsDMEditAble dm can edit
func IsDMEditAble(state int32) bool {
if state == StateNormal || state == StateHide || state == StateMonitorAfter {
return true
}
return false
}
// 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)
}
// DMAttrNtoA convert uint to string format,eg:5-->101-->1,3.
func DMAttrNtoA(attr int32) string {
if attr == 0 {
return ""
}
var bits []int64
for k, v := range strconv.FormatInt(int64(attr), 2) {
if v == 49 {
bits = append(bits, int64(k+1))
}
}
return xstr.JoinInts(bits)
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,53 @@
syntax = "proto3";
package model;
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
option (gogoproto.goproto_enum_prefix_all) = false;
option (gogoproto.goproto_getters_all) = false;
option (gogoproto.unmarshaler_all) = true;
option (gogoproto.marshaler_all) = true;
option (gogoproto.sizer_all) = true;
message DM {
int64 ID = 1 [(gogoproto.jsontag) = "id"];
int32 Type = 2 [(gogoproto.jsontag) = "type"];
int64 Oid = 3 [(gogoproto.jsontag) = "oid"];
int64 Mid = 4 [(gogoproto.jsontag) = "mid"];
int32 Progress = 5 [(gogoproto.jsontag) = "progress"];
int32 Pool = 6 [(gogoproto.jsontag) = "pool"];
int32 Attr = 7 [(gogoproto.jsontag) = "attr"];
int32 State = 8 [(gogoproto.jsontag) = "state"];
int64 Ctime = 9 [(gogoproto.jsontag) = "ctime", (gogoproto.casttype) = "go-common/library/time.Time"];
int64 Mtime = 10 [(gogoproto.jsontag) = "mtime", (gogoproto.casttype) = "go-common/library/time.Time"];
Content Content = 11 [(gogoproto.jsontag) = "content,omitempty"];
ContentSpecial ContentSpe = 12 [(gogoproto.jsontag) = "content_special,omitempty"];
}
message Content {
int64 ID = 1 [(gogoproto.jsontag) = "id"];
int32 FontSize = 2 [(gogoproto.jsontag) = "fontsize"];
int64 Color = 3 [(gogoproto.jsontag) = "color"];
int32 Mode = 4 [(gogoproto.jsontag) = "mode"];
int64 IP = 5 [(gogoproto.jsontag) = "ip"];
int32 Plat = 6 [(gogoproto.jsontag) = "plat"];
string Msg = 7 [(gogoproto.jsontag) = "msg"];
int64 Ctime = 8 [(gogoproto.jsontag) = "ctime", (gogoproto.casttype) = "go-common/library/time.Time"];
int64 Mtime = 9 [(gogoproto.jsontag) = "mtime", (gogoproto.casttype) = "go-common/library/time.Time"];
}
message ContentSpecial {
int64 ID = 1 [(gogoproto.jsontag) = "id"];
string Msg = 2 [(gogoproto.jsontag) = "msg"];
int64 Ctime = 3 [(gogoproto.jsontag) = "ctime", (gogoproto.casttype) = "go-common/library/time.Time"];
int64 Mtime = 4 [(gogoproto.jsontag) = "mtime", (gogoproto.casttype) = "go-common/library/time.Time"];
}
message Elem {
string Attribute = 1 [(gogoproto.jsontag) = "attribute,omitempty"];
string Content = 2 [(gogoproto.jsontag) = "content,omitempty"];
}
message DMSeg {
repeated Elem Elems = 1 [(gogoproto.jsontag) = "dms"];
repeated string SpecialURL = 2 [(gogoproto.jsontag) = "special_url,omitempty"];
}

View File

@@ -0,0 +1,154 @@
package model
import (
"bytes"
"compress/gzip"
"encoding/binary"
"encoding/json"
"fmt"
"io/ioutil"
)
var (
_defaultSeg = &Segment{Start: 0, End: defaultVideoEnd, Cnt: 1, Num: 1, Duration: 0}
// DefaultFlag default dm flag if bigdata downgrade.
DefaultFlag = []byte(`{"rec_flag":2,"rec_text":"开启后,全站视频将按等级等优化弹幕","rec_switch":1,"dmflags":[]}`)
)
const (
// segmentLength 分段长度,6分钟
segmentLength = 60 * 6 * 1000
// defaultVideoEnd 当视频时长不存在或者为0时的默认视频结尾时间点
defaultVideoEnd = int64(10 * 60 * 60 * 1000)
// DefaultVideoEnd 当视频时长不存在或者为0时的默认视频结尾时间点
DefaultVideoEnd = int64(3 * 60 * 60 * 1000)
// DefaultPageSize 默认分段长度
DefaultPageSize = 60 * 6 * 1000
// NotFound nothing found flag
NotFound = int64(-1)
// DefaultPage default page info
// <d p="弹幕ID,弹幕属性,播放时间,弹幕模式,字体大小,颜色,发送时间,弹幕池,用户hash id">弹幕内容</d>
_xmlSegFmt = `<d p="%d,%d,%d,%d,%d,%d,%d,%d,%s">%s</d>`
// <d p="弹幕ID,弹幕属性,播放时间,弹幕模式,字体大小,颜色,发送时间,弹幕池,用户hash id,用户mid">弹幕内容</d>
_xmlSegRealnameFmt = `<d p="%d,%d,%d,%d,%d,%d,%d,%d,%s,%d">%s</d>`
_xmlSegHeader = `<?xml version="1.0" encoding="UTF-8"?><i><oid>%d</oid><ps>%d</ps><pe>%d</pe><pc>%d</pc><pn>%d</pn><state>%d</state><real_name>%d</real_name>`
)
// JudgeSlice sort for dm judgement
type JudgeSlice []*DM
func (d JudgeSlice) Len() int { return len(d) }
func (d JudgeSlice) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
func (d JudgeSlice) Less(i, j int) bool { return d[i].Progress < d[j].Progress }
// Segment dm segment struct
type Segment struct {
Start int64 `json:"ps"` // 分段起始时间
End int64 `json:"pe"` // 分段结束时间
Cnt int64 `json:"cnt"` // 总分段数
Num int64 `json:"num"` // 当前第几段
Duration int64 `json:"duration"` // 视频总时长
}
// DMSegResp segment dm list response
type DMSegResp struct {
Dms []*Elem `json:"dms"`
Flag json.RawMessage `json:"flags,omitempty"`
}
// Page page info.
type Page struct {
Num int64 `json:"num"`
Size int64 `json:"size"`
Total int64 `json:"total"`
}
// ToXMLHeader convert segment to xml header format.
func (s *Segment) ToXMLHeader(oid int64, state, realname int32) string {
return fmt.Sprintf(_xmlSegHeader, oid, s.Start, s.End, s.Cnt, s.Num, state, realname)
}
// SegmentInfo get segment info by start time and video duration.
func SegmentInfo(ps, duration int64) (s *Segment) {
var cnt, num, pe int64
if duration == 0 {
s = _defaultSeg
return
}
cnt = duration / segmentLength
if duration%segmentLength > 0 {
cnt++
}
for i := int64(0); i < cnt; i++ {
if ps >= i*segmentLength && ps < (i+1)*segmentLength {
ps = i * segmentLength
pe = (i + 1) * segmentLength
num = i + 1
}
}
if pe > duration {
pe = duration
}
s = &Segment{
Start: ps,
End: pe,
Cnt: cnt,
Num: num,
Duration: duration,
}
return
}
// Encode dm ecode.
func Encode(flag, xml []byte) (res []byte) {
var (
fl = uint32(len(flag))
xl = uint32(len(xml))
)
res = make([]byte, 4+fl+xl)
binary.BigEndian.PutUint32(res[0:4], fl)
copy(res[4:], flag)
copy(res[4+fl:], xml)
return
}
// Decode decode dm proto.
func Decode(buf []byte) (flag, xml []byte, err error) {
var (
zr *gzip.Reader
)
fl := binary.BigEndian.Uint32(buf[0:4])
flag = buf[4 : 4+fl]
if zr, err = gzip.NewReader(bytes.NewBuffer(buf[4+fl:])); err != nil {
return
}
zr.Close()
if xml, err = ioutil.ReadAll(zr); err != nil {
return
}
return
}
// ToElem convert dm struct to element.
func (d *DM) ToElem() (e *Elem) {
if d.Content == nil {
return
}
msg := d.Content.Msg
if d.ContentSpe != nil {
msg = d.ContentSpe.Msg
}
if len(msg) == 0 {
return
}
if d.Pool == PoolSpecial {
msg = ""
}
// "弹幕ID,弹幕属性,播放时间,弹幕模式,字体大小,颜色,发送时间,弹幕池,用户hash id
e = &Elem{
Attribute: fmt.Sprintf(`"%d,%d,%d,%d,%d,%d,%d,%d,%s"`, d.ID, d.Attr, d.Progress, d.Content.Mode, d.Content.FontSize, d.Content.Color, d.Ctime, d.Pool, Hash(d.Mid, uint32(d.Content.IP))),
Content: msg,
}
return
}

View File

@@ -0,0 +1,23 @@
package model
import (
"strings"
)
// DmSpecial special dm bfs location
type DmSpecial struct {
ID int64
Type int32
Oid int64
Locations string
}
// Split .
func (d *DmSpecial) Split() []string {
return strings.Split(d.Locations, ",")
}
// Join .
func (d *DmSpecial) Join(s []string) {
d.Locations = strings.Join(s, ",")
}

View File

@@ -0,0 +1,64 @@
package model
import (
"go-common/library/time"
)
// all const variable used in dm filter
const (
FilterUnActive int8 = 0
FilterActive int8 = 1
FilterTypeText int8 = 0 // 文本类型
FilterTypeRegex int8 = 1 // 正则类型
FilterTypeID int8 = 2 // 用户ID类型
FilterTypeBottom int8 = 4
FilterTypeTop int8 = 5
FilterTypeRev int8 = 6
FilterLenText = 50 // 文本类型最大字符长度
FilterLenRegex = 200 // 正则类型最大字符长度
FilterMaxUserText = 1000 // 用户关键字最大条数
FilterMaxUserReg = 100 // 用户正则最大条数
FilterMaxUserID = 1000 // 用户黑名单最大条数
FilterMaxUpText = 500 // up主关键字最大条数
FilterMaxUpReg = 100 // up主正则最大条数
FilterMaxUpID = 1000 // up主黑名单最大条数
FilterNotExist = -1000000
FilterContent = "10000,20000,25000,30000"
)
// UserFilter define a new struct, consistent with table "dm_filter_user_%"
type UserFilter struct {
ID int64 `json:"id"`
Mid int64 `json:"mid"`
Type int8 `json:"type"`
Filter string `json:"filter"`
Comment string `json:"comment"`
Ctime time.Time `json:"-"`
Mtime time.Time `json:"-"`
}
// UpFilter filter of upper
type UpFilter struct {
ID int64 `json:"id"`
Mid int64 `json:"mid"`
Type int8 `json:"type"`
Filter string `json:"filter"`
Active int8 `json:"active"`
Comment string `json:"comment"`
Ctime time.Time `json:"ctime"`
Mtime time.Time `json:"mtime"`
}
// GlobalFilter define a new struct, consistent with table "dm_sys_filter"
type GlobalFilter struct {
ID int64 `json:"id"`
Type int8 `json:"type"`
Filter string `json:"filter"`
Ctime time.Time `json:"-"`
Mtime time.Time `json:"-"`
}

View File

@@ -0,0 +1,24 @@
package model
// SearchPage page struct from search
type SearchPage struct {
Num int64 `json:"num"`
Size int64 `json:"size"`
Total int64 `json:"total"`
}
// SearchHistoryResult history dm from search
type SearchHistoryResult struct {
Page *SearchPage `json:"page"`
Result []*struct {
ID int64 `json:"id"`
} `json:"result"`
}
// SearchHistoryIdxResult history date index
type SearchHistoryIdxResult struct {
Page *SearchPage `json:"page"`
Result []*struct {
Date string `json:"date"`
} `json:"result"`
}

View File

@@ -0,0 +1,25 @@
package model
// all const variable used in mask
const (
MaskPlatWeb int8 = 0
MaskPlatMbl int8 = 1
)
// MaskLists mask lists
type MaskLists struct {
Onoff int64 `json:"onoff"`
Cid int64 `json:"cid,omitempty"`
Fps int64 `json:"fps,omitempty"`
Time int64 `json:"time,omitempty"`
Lists []string `json:"list,omitempty"`
}
// Mask mask info
type Mask struct {
Cid int64 `json:"cid,omitempty"`
Plat int8 `json:"plat,omitempty"`
FPS int32 `json:"fps,omitempty"`
Time int64 `json:"time,omitempty"`
MaskURL string `json:"mask_url,omitempty"`
}

View File

@@ -0,0 +1,137 @@
package model
import (
"go-common/library/time"
)
//CondIntNil cond int nil
const CondIntNil = -10516
// DmRecentResponse .
type DmRecentResponse struct {
Page *Page `json:"page"`
Data []*DMMember `json:"result"`
}
// Recent recent dm
type Recent struct {
ID int64 `json:"id"`
Type int32 `json:"type"`
Aid int64 `json:"pid"`
Oid int64 `json:"oid"`
Mid int64 `json:"mid"`
Pool int32 `json:"pool"`
Attr int32 `json:"attr"`
Progress int32 `json:"progress"`
Mode int32 `json:"mode"`
Msg string `json:"msg"`
State int32 `json:"state"`
FontSize int32 `json:"fontsize"`
Color int32 `json:"color"`
Ctime string `json:"ctime"`
}
// DMMember dm struct used in member
type DMMember struct {
ID int64 `json:"id"`
IDStr string `json:"id_str"`
Type int32 `json:"type"`
Aid int64 `json:"aid"`
Oid int64 `json:"oid"`
Mid int64 `json:"mid"`
MidHash string `json:"mid_hash"`
Pool int32 `json:"pool"`
Attrs string `json:"attrs"`
Progress int32 `json:"progress"`
Mode int32 `json:"mode"`
Msg string `json:"msg"`
State int32 `json:"state"`
FontSize int32 `json:"fontsize"`
Color string `json:"color"`
Ctime time.Time `json:"ctime"`
Uname string `json:"uname"`
Title string `json:"title"`
}
// SearchDMParams dm search params
type SearchDMParams struct {
Type int32
Oid int64
Keyword string
Mids string
Mode string
Pool string
Attrs string
ProgressFrom int64
ProgressTo int64
CtimeFrom string
CtimeTo string
Pn int64
Ps int64
Sort string
Order string
State string
}
// SearchRecentDMParam .
type SearchRecentDMParam struct {
Type int32
UpMid int64
States []int32
Ps int
Pn int
Sort string
Field string
}
// SearchRecentDMResult .
type SearchRecentDMResult struct {
Page *Page `json:"page"`
Result []*Recent `json:"result"`
}
// SearchDMData dm meta data from search
type SearchDMData struct {
Result []*struct {
ID int64 `json:"id"`
} `json:"result"`
Page *SearchPage
}
//SearchDMResult dm list
type SearchDMResult struct {
Page struct {
Num int64 `json:"num"`
Size int64 `json:"size"`
Total int64 `json:"total"`
} `json:"page"`
Result []*DMMember `json:"result"`
}
// 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"`
}

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/interface/main/dm2/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,79 @@
package oplog
import (
"go-common/library/log"
)
// Infoc operation log for administrator
type Infoc struct {
Oid int64 `json:"oid"`
Type int `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"`
}
// 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)", int(source))
text = "未知来源"
}
return text
}
// OperatorType enum integer value
type OperatorType int
// OperatorType enum definition list
const (
_ OperatorType = iota
OperatorAdmin
OperatorMember
OperatorUp
OperatorSystem
)
// String returns the Source enmu description
func (opType OperatorType) String() string {
var text string
switch opType {
case OperatorAdmin:
text = "管理员"
case OperatorMember:
text = "用户"
case OperatorUp:
text = "UP主"
case OperatorSystem:
text = "系统"
default:
log.Warn("String() Unknow Source, warn(%v)", int(opType))
text = "未知来源"
}
return text
}

View File

@@ -0,0 +1,12 @@
package model
// SubtitleReportAddParam .
type SubtitleReportAddParam struct {
Oid int64 `form:"oid" validate:"required"`
SubtitleID int64 `form:"subtitle_id" validate:"required"`
Tid int64 `form:"tid" validate:"required"`
MetaData string `form:"metadata" validate:"lt=300"`
From float64 `form:"from"`
To float64 `form:"to" validate:"required"`
Content string `form:"content" validate:"required"`
}

View File

@@ -0,0 +1,163 @@
package model
import "go-common/app/interface/main/dm2/model/oplog"
// ArgOids arguments passed by rpc client
type ArgOids struct {
Type int32
Plat int8
Oids []int64
RealIP string
}
// ArgEditDMState arguments passed by rpc client
type ArgEditDMState struct {
Type int32
Oid int64
Mid int64
State int32
Dmids []int64
Source oplog.Source
OperatorType oplog.OperatorType
}
// ArgEditDMPool arguments passed by rpc client
type ArgEditDMPool struct {
Type int32
Oid int64
Mid int64
Pool int32
Dmids []int64
Source oplog.Source
OperatorType oplog.OperatorType
}
// ArgEditDMAttr edit dm attr,bit: AttrXXX defined in model,value:AttrYes/AttrNo
type ArgEditDMAttr struct {
Type int32
Oid int64
Mid int64
Bit uint
Value int32
Dmids []int64
Source oplog.Source
OperatorType oplog.OperatorType
}
// ArgAdvance arguments passed by rpc client
type ArgAdvance struct {
Mid int64
Cid int64
Mode string
}
// ArgMid arguments passed by rpc client
type ArgMid struct {
Mid int64
}
// ArgUpAdvance arguments passed by rpc client
type ArgUpAdvance struct {
Mid int64
ID int64
}
// ArgAddUserFilters add user filters
type ArgAddUserFilters struct {
Type int8
Mid int64
Filters []string
Comment string
}
// ArgDelUserFilters delete user filter
type ArgDelUserFilters struct {
Mid int64
IDs []int64
}
// ArgAddUpFilters add up filters
type ArgAddUpFilters struct {
Type int8
Mid int64
Filters []string
}
// ArgUpFilters up filters
type ArgUpFilters struct {
Mid int64
}
// ArgEditUpFilters edit up filter
type ArgEditUpFilters struct {
Type int8
Mid int64
Active int8
Filters []string
}
// ArgAddGlobalFilter add global filter
type ArgAddGlobalFilter struct {
Type int8
Filter string
}
// ArgGlobalFilters get global filter
type ArgGlobalFilters struct {
}
// ArgDelGlobalFilters delete global filters
type ArgDelGlobalFilters struct {
IDs []int64
}
// ArgBanUsers ban users
type ArgBanUsers struct {
Mid int64
Oid int64
DMIDs []int64
}
// ArgCancelBanUsers cancel banned users
type ArgCancelBanUsers struct {
Mid int64
Aid int64
Filters []string
}
// ArgCid arg cid
type ArgCid struct {
Cid int64
}
// ArgSubtitleGet .
type ArgSubtitleGet struct {
Aid int64
Oid int64
Type int32
}
// ArgSubtitleAllowSubmit .
type ArgSubtitleAllowSubmit struct {
Aid int64
AllowSubmit bool
Lan string
}
// SubtitleSubjectReply .
type SubtitleSubjectReply struct {
AllowSubmit bool
Lan string
LanDoc string
}
// ArgArchiveID .
type ArgArchiveID struct {
Aid int64
}
// ArgMask .
type ArgMask struct {
Cid int64
Plat int8
}

View File

@@ -0,0 +1,86 @@
package model
import (
"go-common/library/time"
)
// All const variable used in dm subject
const (
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"`
}
// ViewVideoSubtitle .
type ViewVideoSubtitle struct {
Author *ViewAuthor `json:"author,omitempty"`
ID int64 `json:"id"`
Lan string `json:"lan"`
LanDoc string `json:"lan_doc"`
SubtitleURL string `json:"subtitle_url"`
}
// ViewAuthor .
type ViewAuthor struct {
Mid int64 `json:"mid"`
Name string `json:"name"`
Sex string `json:"sex"`
Face string `json:"face"`
Sign string `json:"sign"`
Rank int32 `json:"rank"`
}
// 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)
}
// SubjectInfo dm subject info
type SubjectInfo struct {
Closed bool `json:"closed"`
Realname bool `json:"real_name"`
Count int64 `json:"count"`
MaskList Mask `json:"mask"`
VideoSubtitle []*ViewVideoSubtitle `json:"subtitles"`
}
// 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,406 @@
package model
import (
"go-common/library/ecode"
)
// SubtitleLocation .
const (
SubtitleLocationLeftBottom = uint8(1) //左下角
SubtitleLocationBottomMid = uint8(2) //底部居中
SubtitleLocationRightBottom = uint8(3) //右下角
SubtitleLocationLeftUp = uint8(7) //左上角
SubtitleLocationUpMid = uint8(8) //顶部居中
SubtitleLocationRightUp = uint8(9) //右上角
SubtitleContentSizeLimit = 300
)
var (
// SubtitleLocationMap .
SubtitleLocationMap = map[uint8]struct{}{
SubtitleLocationLeftBottom: {},
SubtitleLocationBottomMid: {},
SubtitleLocationRightBottom: {},
SubtitleLocationLeftUp: {},
SubtitleLocationUpMid: {},
SubtitleLocationRightUp: {},
}
)
// SubtitleStatus .
type SubtitleStatus uint8
// SubtitleStatus
const (
SubtitleStatusUnknown SubtitleStatus = iota
SubtitleStatusDraft
SubtitleStatusToAudit
SubtitleStatusAuditBack
SubtitleStatusRemove
SubtitleStatusPublish
SubtitleStatusCheckToAudit
SubtitleStatusCheckPublish
SubtitleStatusManagerBack
SubtitleStatusManagerRemove
)
// UpperStatus .
type UpperStatus uint8
// UpperStatus
const (
UpperStatusUnknow UpperStatus = iota
UpperStatusUpper
)
// AuthorStatus .
type AuthorStatus uint8
// AuthorStatus
const (
AuthorStatusUnknow AuthorStatus = iota
AuthorStatusAuthor
)
// WaveFormStatus .
type WaveFormStatus uint8
//WaveFormStatus
const (
WaveFormStatusWaitting WaveFormStatus = iota
WaveFormStatusSuccess
WaveFormStatusFailed
WaveFormStatusError // this status need retry
)
// 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"`
CheckSum string `json:"-"`
SubtitleURL string `json:"subtitle_url"`
PubTime int64 `json:"pub_time"`
RejectComment string `json:"reject_comment"`
Mtime int64 `json:"mtime"`
Empty bool `json:"empty"`
}
// SubtitleShow .
type SubtitleShow struct {
ID int64 `json:"id"`
Oid int64 `json:"oid"`
Type int32 `json:"type"`
Lan string `json:"lan"`
LanDoc string `json:"lan_doc"`
Mid int64 `json:"mid"`
Author string `json:"author"`
Aid int64 `json:"aid"`
ArchiveName string `json:"archive_name"`
IsSign bool `json:"is_sign"`
IsLock bool `json:"is_lock"`
Status SubtitleStatus `json:"status"`
SubtitleURL string `json:"subtitle_url"`
RejectComment string `json:"reject_comment"`
AuthorStatus AuthorStatus `json:"author_status"` // 1:作者
UpperStatus UpperStatus `json:"upper_status"` // 1:up主
}
// SubtitlePub .
type SubtitlePub struct {
Oid int64 `json:"oid"`
Type int32 `json:"type"`
Lan uint8 `json:"lan"`
SubtitleID int64 `json:"subtitle_id"`
IsDelete bool `json:"is_delete"`
}
// VideoSubtitles .
type VideoSubtitles struct {
AllowSubmit bool `json:"allow_submit"`
Lan string `json:"lan"`
LanDoc string `json:"lan_doc"`
Subtitles []*VideoSubtitle `json:"subtitles"`
}
// VideoSubtitleCache .
type VideoSubtitleCache struct {
VideoSubtitles []*VideoSubtitle `json:"video_subtitles"`
}
// VideoSubtitle .
type VideoSubtitle struct {
ID int64 `json:"id"`
Lan string `json:"lan"`
LanDoc string `json:"lan_doc"`
IsLock bool `json:"is_lock"`
AuthorMid int64 `json:"author_mid,omitempty"`
SubtitleURL string `json:"subtitle_url"`
}
// Language .
type Language struct {
Lan string `json:"lan"`
LanDoc string `json:"lan_doc"`
Pub *LanguagePub `json:"pub,omitempty"`
Draft *LanguageID `json:"draft,omitempty"`
Audit *LanguageID `json:"audit,omitempty"`
AuditBack *LanguageID `json:"audit_back,omitempty"`
}
// LanguagePub .
type LanguagePub struct {
SubtitleID int64 `json:"subtitle_id"`
IsLock bool `json:"is_lock"`
IsPub bool `json:"is_pub"`
}
// LanguageID .
type LanguageID struct {
SubtitleID int64 `json:"subtitle_id"`
}
// SubtitlePageResult .
type SubtitlePageResult struct {
ID int64 `json:"id"`
Oid int64 `json:"oid"`
}
// CountSubtitleResult .
type CountSubtitleResult struct {
Draft int64
ToAudit int64
AuditBack int64
Publish int64
}
// SearchSubtitleResult .
type SearchSubtitleResult struct {
Page *SearchPage `json:"page"`
Results []*SubtitlePageResult `json:"result"`
}
// SearchSubtitle .
type SearchSubtitle struct {
ID int64 `json:"id"`
Oid int64 `json:"oid"`
Aid int64 `json:"aid"`
Type int32 `json:"type"`
ArchiveName string `json:"archive_name"`
VideoName string `json:"video_name"`
ArchivePic string `json:"archive_pic"`
AuthorID int64 `json:"author_id"`
Author string `json:"author"`
AuthorPic string `json:"author_pic"`
Lan string `json:"lan"`
LanDoc string `json:"lan_doc"`
Status int32 `json:"status"`
IsSign bool `json:"is_sign"`
IsLock bool `json:"is_lock"`
RejectComment string `json:"reject_comment"`
Mtime int64 `json:"mtime"`
}
// SearchSubtitleResponse .
type SearchSubtitleResponse struct {
Page *SearchPage `json:"page"`
Subtitles []*SearchSubtitle `json:"subtitles"`
}
// SearchSubtitleAuthorItem .
type SearchSubtitleAuthorItem struct {
ID int64 `json:"id"`
Oid int64 `json:"oid"`
Aid int64 `json:"aid"`
Type int32 `json:"type"`
ArchiveName string `json:"archive_name"`
VideoName string `json:"video_name"`
ArchivePic string `json:"archive_pic"`
Lan string `json:"lan"`
LanDoc string `json:"lan_doc"`
Status int32 `json:"status"`
IsSign bool `json:"is_sign"`
IsLock bool `json:"is_lock"`
RejectComment string `json:"reject_comment"`
Mtime int64 `json:"mtime"`
}
// SearchSubtitleAuthor .
type SearchSubtitleAuthor struct {
Page *SearchPage `json:"page"`
Subtitles []*SearchSubtitleAuthorItem `json:"subtitles"`
Total int64 `json:"total"`
DraftCount int64 `json:"draft_count"`
AuditCount int64 `json:"audit_count"`
BackCount int64 `json:"back_count"`
PublishCount int64 `json:"publish_count"`
}
// SearchSubtitleAssit .
type SearchSubtitleAssit struct {
Page *SearchPage `json:"page"`
Subtitles []*SearchSubtitle `json:"subtitles"`
Total int64 `json:"total"`
AuditCount int64 `json:"audit_count"`
PublishCount int64 `json:"publish_count"`
}
// 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"`
Empty bool `json:"empty"`
}
// 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)
}
// SubtitleItem .
type SubtitleItem struct {
From float64 `json:"from"`
To float64 `json:"to"`
Location uint8 `json:"location"`
Content string `json:"content"`
}
// SubtitleBody .
type SubtitleBody struct {
FontSize float64 `json:"font_size,omitempty"`
FontColor string `json:"font_color,omitempty"`
BackgroundAlpha float64 `json:"background_alpha,omitempty"`
BackgroundColor string `json:"background_color,omitempty"`
Stroke string `json:"Stroke,omitempty"`
Bodys []*SubtitleItem `json:"body"`
}
// CheckItem .
// err 兼容老接口error等创作中心上线后去掉error返回
func (s *SubtitleBody) CheckItem(duration int64) (detectErrs []*SubtitleDetectError, err error) {
var (
maxDuration = float64(duration) / float64(1000)
)
maxDuration = maxDuration + 1 // 时间刻度上线兼容1
for idx, item := range s.Bodys {
if len(item.Content) > SubtitleContentSizeLimit {
detectErrs = append(detectErrs, &SubtitleDetectError{
Line: int32(idx),
ErrorMsg: ecode.SubtitleSizeLimit.Message(),
})
err = ecode.SubtitleSizeLimit
continue
}
if _, ok := SubtitleLocationMap[item.Location]; !ok {
detectErrs = append(detectErrs, &SubtitleDetectError{
Line: int32(idx),
ErrorMsg: ecode.SubtitleLocationUnValid.Message(),
})
err = ecode.SubtitleSizeLimit
continue
}
if item.From >= item.To {
detectErrs = append(detectErrs, &SubtitleDetectError{
Line: int32(idx),
ErrorMsg: ecode.SubtitleDuarionMustThanZero.Message(),
})
err = ecode.SubtitleSizeLimit
continue
}
if item.From > maxDuration || item.To > maxDuration {
detectErrs = append(detectErrs, &SubtitleDetectError{
Line: int32(idx),
ErrorMsg: ecode.SubtitleVideoDurationOverFlow.Message(),
})
err = ecode.SubtitleSizeLimit
continue
}
}
return
}
// WaveForm .
type WaveForm struct {
Oid int64 `json:"oid"`
Type int32 `json:"type"`
State WaveFormStatus `json:"state"`
WaveFromURL string `json:"wave_form_url"`
Mtime int64 `json:"mtime"`
Empty bool
}
// WaveFormResp .
type WaveFormResp struct {
State WaveFormStatus `json:"state"`
WaveFromURL string `json:"wave_form_url"`
}
// SubtitleLans .
type SubtitleLans []*SubtitleLan
// SubtitleLan .
type SubtitleLan struct {
Code int64 `json:"-"`
Lan string `json:"lan"`
DocZh string `json:"doc_zh"`
DocEn string `json:"-"`
IsDelete bool `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
}
// SubtitleCheckMsg .
type SubtitleCheckMsg struct {
SubtitleID int64 `json:"subtitle_id"`
Oid int64 `json:"oid"`
}
// FilterCheckResp .
type FilterCheckResp struct {
Hits map[string]string `json:"hits"`
}
// SubtitleDetectError .
type SubtitleDetectError struct {
Line int32 `json:"line"`
ErrorMsg string `json:"error_msg"`
}

View File

@@ -0,0 +1,23 @@
package model
// All const variable used in thumbup
const (
ThumbupLike int8 = 1 // 点赞
ThumbupLikeCancel int8 = 2 // 取消赞
ThumbupHate int8 = 3 // 点踩
ThumbupHateCancel int8 = 4 // 取消踩
)
// ThumbupStat thumbup state
type ThumbupStat struct {
Likes int64 `json:"likes"`
UserLike int8 `json:"user_like"`
}
// CheckThumbup check thumbup.
func CheckThumbup(Thumbup int8) bool {
if Thumbup == ThumbupLikeCancel || Thumbup == ThumbupLike || Thumbup == ThumbupHateCancel || Thumbup == ThumbupHate {
return true
}
return false
}

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