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 ( // 弹幕内容 _xmlFmt = `%s` // 弹幕内容 _rnameFmt = `%s` 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(`%s`, 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 { // 弹幕内容 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 { // 弹幕内容 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 { // 弹幕内容 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 { // 弹幕内容 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) }