go-common/app/interface/main/push-archive/dao/fan_group.go

183 lines
5.5 KiB
Go
Raw Normal View History

2019-04-22 10:49:16 +00:00
package dao
import (
"bytes"
"encoding/hex"
"fmt"
"os"
"strconv"
"strings"
"time"
"go-common/app/interface/main/push-archive/conf"
"go-common/app/interface/main/push-archive/model"
"go-common/library/log"
)
// FanGroup 粉丝分组
type FanGroup struct {
// 组名
Name string
// 粉丝与up主的关注关系
RelationType int
Hitby string
// 限制条数
Limit int
PerUpperLimit int
LimitExpire int32
// 本组获取粉丝的hbase信息
HBaseTable string
HBaseFamily []string
MsgTemplateDesc string
MsgTemplate string
}
func fanGroupKey(relationType int, name string) string {
return fmt.Sprintf(`%d#%s`, relationType, name)
}
// NewFanGroups 实例化,验证配置, 若配置错误则panic
func NewFanGroups(config *conf.Config) (grp map[string]*FanGroup) {
grp = make(map[string]*FanGroup)
for _, g := range config.ArcPush.FanGroup {
if g.Name == "" {
log.Error("NewFanGroups config ArcPush.FanGroup.Name/hitby must not be empty")
break
}
// 粉丝和up主的关系配置验证
if g.RelationType != model.RelationAttention && g.RelationType != model.RelationSpecial {
log.Error("NewFanGroups config ArcPush.FanGroup.RelationType not exist(%d)", g.RelationType)
break
}
if g.Hitby != model.GroupDataTypeDefault && g.Hitby != model.GroupDataTypeHBase &&
g.Hitby != model.GroupDataTypeAbtest && g.Hitby != model.GroupDataTypeAbComparison {
log.Error("NewFanGroups config ArcPush.FanGroup.hitby(%s) must in [default,hbase]", g.Hitby)
break
}
key := fanGroupKey(g.RelationType, g.Name)
if _, ok := grp[key]; ok {
log.Error("NewFanGroups config ArcPush.FanGroup.relationtype(%d) and name(%s) must be unique", g.RelationType, g.Name)
break
}
// hbase配置
if g.HBaseTable != "" && len(g.HBaseFamily) == 0 {
log.Error("NewFanGroups config ArcPush.FanGroup.HbaseTable(%s) & HbaseFamily(%v) must exist togather", g.HBaseTable, g.HBaseFamily)
break
}
msgTemp, err := decodeMsgTemplate(g.Name, g.MsgTemplate)
if err != nil {
log.Error("NewFanGroups config ArcPush.FanGroup.MsgTemplate(%s) decodeMsgTemplate error(%v)", g.MsgTemplate, err)
break
}
if msgTemp != g.MsgTemplateDesc {
log.Error("NewFanGroups config ArcPush.FanGroup.MsgTemplate decodeMsgTemplate(%s) must equal to MsgTemplateDesc(%s)", msgTemp, g.MsgTemplateDesc)
break
}
if len(strings.SplitN(msgTemp, "\r\n", 2)) != 2 {
log.Error("NewFanGroups config ArcPush.FanGroup.MsgTemplate(%s) decodeMsgTemplate(%s) must contains `\r\n`", g.MsgTemplate, msgTemp)
break
}
grp[key] = &FanGroup{
Name: strings.TrimSpace(g.Name),
RelationType: g.RelationType,
Hitby: strings.TrimSpace(g.Hitby),
Limit: g.Limit,
PerUpperLimit: g.PerUpperLimit,
LimitExpire: int32(time.Duration(g.LimitExpire) / time.Second),
HBaseTable: strings.TrimSpace(g.HBaseTable),
HBaseFamily: g.HBaseFamily,
MsgTemplateDesc: g.MsgTemplateDesc,
MsgTemplate: msgTemp,
}
}
if len(grp) < len(config.ArcPush.FanGroup) {
fmt.Printf("NewFanGroups failed\r\n\r\n")
os.Exit(1)
}
return
}
// decodeMsgTemplate 将ascii格式的文案模版解码成中文格式---防止某些服务器不支持中文配置
func decodeMsgTemplate(groupName string, temp string) (decode string, err error) {
if temp == "" {
return
}
b, err := hex.DecodeString(temp)
if err != nil {
log.Error("DecodeMsgTemplate hex.DecodeString error(%v) groupName(%s), temp(%s)", err, groupName, temp)
return
}
buf := new(bytes.Buffer)
temp = string(b)
rows := strings.Split(temp[1:len(temp)-1], "\\r\\n")
lenRows := len(rows) - 1
for k, row := range rows {
parts := strings.Split(row, "%s")
lenParts := len(parts) - 1
for kp, str := range parts {
words := strings.Split(str, "\\u")
for _, w := range words {
if len(w) < 1 {
continue
}
wi, err := strconv.ParseInt(w, 16, 32)
if err != nil {
log.Error("DecodeMsgTemplate error(%v) groupName(%s), decode(%s), word(%s)", err, groupName, temp, w)
return "", err
}
buf.WriteString(fmt.Sprintf("%c", wi))
}
if kp >= lenParts {
continue
}
buf.WriteString("%s")
}
if k >= lenRows {
continue
}
buf.WriteString("\r\n")
}
decode = buf.String()
return
}
// FansByHBase hbase表中查询粉丝所关联的up主过滤up不在hbase结果中的粉丝
func (d *Dao) FansByHBase(upper int64, fanGroupKey string, fans *[]int64) (result []int64, excluded []int64) {
g := d.FanGroups[fanGroupKey]
// 不过滤
if len(g.HBaseTable) == 0 {
result = *fans
return
}
params := model.NewBatchParam(map[string]interface{}{
"base": upper,
"table": g.HBaseTable,
"family": g.HBaseFamily,
"result": &result,
"excluded": &excluded,
"handler": d.filterFanByUpper,
}, nil)
Batch(fans, 100, 1, params, d.FilterFans)
return
}
// FansByActiveTime 配置了默认活跃时间,则批量过滤粉丝是否在活跃时间段内,否则不推送;未配置则不过滤活跃时间;若希望没有默认活跃时间但希望过滤活跃时间,配置成[0]
func (d *Dao) FansByActiveTime(hour int, fans *[]int64) (result []int64, excluded []int64) {
// 未配置则不过滤活跃时间
if len(d.ActiveDefaultTime) <= 0 {
result = *fans
excluded = []int64{}
return
}
params := model.NewBatchParam(map[string]interface{}{
"base": hour,
"table": "dm_member_push_active_hour",
"family": []string{"p"},
"result": &result,
"excluded": &excluded,
"handler": d.filterFanByActive,
}, nil)
Batch(fans, 100, 1, params, d.FilterFans)
return
}