183 lines
5.5 KiB
Go
183 lines
5.5 KiB
Go
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
|
||
}
|