go-common/app/interface/main/dm2/model/dm.go
2019-04-22 18:49:16 +08:00

299 lines
7.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package model
import (
"fmt"
"hash/crc32"
"strconv"
"go-common/library/time"
"go-common/library/xstr"
)
var (
bAmp = []byte(`&`)
bGt = []byte(`>`)
bLt = []byte(`<`)
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)
}