You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

244 lines
5.4 KiB

package model
import (
"bytes"
"crypto/md5"
"encoding/json"
"fmt"
"math"
"net/url"
"strconv"
"strings"
"time"
"go-common/library/log"
"github.com/dgryski/go-farm"
)
// SplitInts splts string to int-slice by ,
func SplitInts(s string) (res []int) {
if s == "" {
return
}
ints := strings.Split(s, ",")
for _, v := range ints {
i, _ := strconv.Atoi(v)
res = append(res, i)
}
return
}
// JoinInts merges int slice to string.
func JoinInts(ints []int) string {
if len(ints) == 0 {
return ""
}
if len(ints) == 1 {
return strconv.Itoa(ints[0])
}
buf := bytes.Buffer{}
for _, v := range ints {
buf.WriteString(strconv.Itoa(v))
buf.WriteString(",")
}
if buf.Len() > 0 {
buf.Truncate(buf.Len() - 1)
}
return buf.String()
}
// ExistsInt judge if item in the ints.
func ExistsInt(ints []int, item int) (exists bool) {
for _, i := range ints {
if i == item {
return true
}
}
return false
}
// HashToken gets token's hash value.
func HashToken(token string) int64 {
return int64(farm.Hash64([]byte(token)) % math.MaxInt64)
}
// RealTime culculates real time by timezone.
func RealTime(reportZone int) time.Time {
now := time.Now()
_, offset := now.Zone()
return now.Add(time.Duration(reportZone-offset/3600) * time.Hour)
}
// Scheme gets uri scheme.
func Scheme(typ int8, val string, platform, build int) (uri string) {
switch typ {
case LinkTypeBangumi: // 番剧
if platform == PlatformAndroid {
uri = SchemeBangumiSeasonAndroid + val
} else {
uri = SchemeBangumiSeasonIOS + val
}
case LinkTypeVideo: // 视频
if platform == PlatformAndroid {
uri = SchemeVideoAndroid + val
} else {
uri = SchemeVideoIOS + val
}
case LinkTypeLive:
var (
param string
parts = strings.Split(val, ",") // 值可能为 1 或者 1,0
)
if len(parts) == 2 {
param = "?broadcast_type=" + parts[1]
}
uri = SchemeLive + parts[0] + param
if platform == PlatformAndroid && build < 5290000 {
uri = SchemeLiveAndroid + parts[0]
}
case LinkTypeSplist: // 专题
uri = SchemeSplist + val
case LinkTypeAuthor: // 个人空间
if platform == PlatformAndroid {
uri = SchemeAuthorAndroid + val
} else {
uri = SchemeAuthorIOS + val
}
case LinkTypeSearch: // 搜索
if platform == PlatformAndroid {
uri = SchemeSearchAndroid + val
} else {
uri = SchemeSearchIOS + val
}
case LinkTypeBrowser: // H5
if platform == PlatformAndroid {
uri = SchemeBrowserAndroid + url.QueryEscape(val)
} else {
// 容错逻辑,标准写法是 SchemeBrowserIOS + val,且 val 需要业务方进行 urlencode
// 但是老客户端有bug,客户端会强制encode,客户端从 5.28 开始修了这个bug
// 版本覆盖完全后,可改成标准写法
uri = val
}
case LinkTypeVipBuy:
uri = SchemeVipBuy + val
case LinkTypeCustom:
uri = val
default:
uri = ""
}
return
}
// ParseBuild parses string to build struct.
func ParseBuild(s string) (builds map[int]*Build) {
builds = make(map[int]*Build)
if s == "" {
return
}
temp := make(map[string]*Build)
if err := json.Unmarshal([]byte(s), &temp); err != nil {
log.Error("json.Unmarshal(%s) error(%v)", s, err)
return
}
for plat, build := range temp {
p, _ := strconv.Atoi(plat)
builds[p] = build
}
return
}
// TempTaskID gen temporary task ID.
func TempTaskID() string {
n := time.Now().UnixNano()
m := md5.Sum([]byte(strconv.FormatInt(n, 10)))
return TempTaskPrefix + fmt.Sprintf("%x", m)[:8] // 要把taskid当作jobkey参数,jobkey要求长度最多9位, 1位prefix+8位时间hash值前段
}
// JobName gen job name.
func JobName(timestamp int64, content, linkValue, group string) int64 {
s := []byte(fmt.Sprintf("%d%s%s%s%s", timestamp, time.Now().Format("20060102"), content, linkValue, group))
return int64(farm.Hash64(s) % math.MaxInt64)
}
// Hash gen hash value by solt.
func Hash(salt string) string {
s := salt + strconv.FormatInt(time.Now().UnixNano(), 10)
return fmt.Sprintf("%x", md5.Sum([]byte(s)))
}
// 免打扰时间默认值
const (
_defaultSilentBeginHour = 22
_defaultSilentEndHour = 8
_defaultSilentBeginMinute = 0
_defaultSilentEndMinute = 0
)
// ParseSilentTime .
func ParseSilentTime(s string) (st BusinessSilentTime) {
st = BusinessSilentTime{
BeginHour: _defaultSilentBeginHour,
EndHour: _defaultSilentEndHour,
BeginMinute: _defaultSilentBeginMinute,
EndMinute: _defaultSilentEndMinute,
}
s = strings.Trim(s, " ")
if s == "" {
return
}
r := strings.Split(s, "-")
if len(r) != 2 {
return
}
begin := strings.Split(r[0], ":")
if len(begin) == 2 {
st.BeginHour, _ = strconv.Atoi(begin[0])
st.BeginMinute, _ = strconv.Atoi(begin[1])
}
end := strings.Split(r[1], ":")
if len(end) == 2 {
st.EndHour, _ = strconv.Atoi(end[0])
st.EndMinute, _ = strconv.Atoi(end[1])
}
return st
}
// IsAndroid .
func IsAndroid(platformID int) bool {
m := map[int]bool{
PlatformIPhone: true,
PlatformIPad: true,
}
return !m[platformID]
}
// ValidateBuild checks token&platform valid.
func ValidateBuild(platform, build int, builds map[int]*Build) bool {
if len(builds) == 0 {
return true
}
if IsAndroid(platform) {
platform = PlatformAndroid
}
if builds[platform] == nil {
return true
}
c := builds[platform].Condition
b := builds[platform].Build
switch c {
case "gt":
return build > b
case "gte":
return build >= b
case "lt":
return build < b
case "lte":
return build <= b
case "eq":
return build == b
case "ne":
return build != b
}
return false
}