245 lines
5.4 KiB
Go
245 lines
5.4 KiB
Go
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
|
||
}
|