functions.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. package model
  2. import (
  3. "bytes"
  4. "crypto/md5"
  5. "encoding/json"
  6. "fmt"
  7. "math"
  8. "net/url"
  9. "strconv"
  10. "strings"
  11. "time"
  12. "go-common/library/log"
  13. "github.com/dgryski/go-farm"
  14. )
  15. // SplitInts splts string to int-slice by ,
  16. func SplitInts(s string) (res []int) {
  17. if s == "" {
  18. return
  19. }
  20. ints := strings.Split(s, ",")
  21. for _, v := range ints {
  22. i, _ := strconv.Atoi(v)
  23. res = append(res, i)
  24. }
  25. return
  26. }
  27. // JoinInts merges int slice to string.
  28. func JoinInts(ints []int) string {
  29. if len(ints) == 0 {
  30. return ""
  31. }
  32. if len(ints) == 1 {
  33. return strconv.Itoa(ints[0])
  34. }
  35. buf := bytes.Buffer{}
  36. for _, v := range ints {
  37. buf.WriteString(strconv.Itoa(v))
  38. buf.WriteString(",")
  39. }
  40. if buf.Len() > 0 {
  41. buf.Truncate(buf.Len() - 1)
  42. }
  43. return buf.String()
  44. }
  45. // ExistsInt judge if item in the ints.
  46. func ExistsInt(ints []int, item int) (exists bool) {
  47. for _, i := range ints {
  48. if i == item {
  49. return true
  50. }
  51. }
  52. return false
  53. }
  54. // HashToken gets token's hash value.
  55. func HashToken(token string) int64 {
  56. return int64(farm.Hash64([]byte(token)) % math.MaxInt64)
  57. }
  58. // RealTime culculates real time by timezone.
  59. func RealTime(reportZone int) time.Time {
  60. now := time.Now()
  61. _, offset := now.Zone()
  62. return now.Add(time.Duration(reportZone-offset/3600) * time.Hour)
  63. }
  64. // Scheme gets uri scheme.
  65. func Scheme(typ int8, val string, platform, build int) (uri string) {
  66. switch typ {
  67. case LinkTypeBangumi: // 番剧
  68. if platform == PlatformAndroid {
  69. uri = SchemeBangumiSeasonAndroid + val
  70. } else {
  71. uri = SchemeBangumiSeasonIOS + val
  72. }
  73. case LinkTypeVideo: // 视频
  74. if platform == PlatformAndroid {
  75. uri = SchemeVideoAndroid + val
  76. } else {
  77. uri = SchemeVideoIOS + val
  78. }
  79. case LinkTypeLive:
  80. var (
  81. param string
  82. parts = strings.Split(val, ",") // 值可能为 1 或者 1,0
  83. )
  84. if len(parts) == 2 {
  85. param = "?broadcast_type=" + parts[1]
  86. }
  87. uri = SchemeLive + parts[0] + param
  88. if platform == PlatformAndroid && build < 5290000 {
  89. uri = SchemeLiveAndroid + parts[0]
  90. }
  91. case LinkTypeSplist: // 专题
  92. uri = SchemeSplist + val
  93. case LinkTypeAuthor: // 个人空间
  94. if platform == PlatformAndroid {
  95. uri = SchemeAuthorAndroid + val
  96. } else {
  97. uri = SchemeAuthorIOS + val
  98. }
  99. case LinkTypeSearch: // 搜索
  100. if platform == PlatformAndroid {
  101. uri = SchemeSearchAndroid + val
  102. } else {
  103. uri = SchemeSearchIOS + val
  104. }
  105. case LinkTypeBrowser: // H5
  106. if platform == PlatformAndroid {
  107. uri = SchemeBrowserAndroid + url.QueryEscape(val)
  108. } else {
  109. // 容错逻辑,标准写法是 SchemeBrowserIOS + val,且 val 需要业务方进行 urlencode
  110. // 但是老客户端有bug,客户端会强制encode,客户端从 5.28 开始修了这个bug
  111. // 版本覆盖完全后,可改成标准写法
  112. uri = val
  113. }
  114. case LinkTypeVipBuy:
  115. uri = SchemeVipBuy + val
  116. case LinkTypeCustom:
  117. uri = val
  118. default:
  119. uri = ""
  120. }
  121. return
  122. }
  123. // ParseBuild parses string to build struct.
  124. func ParseBuild(s string) (builds map[int]*Build) {
  125. builds = make(map[int]*Build)
  126. if s == "" {
  127. return
  128. }
  129. temp := make(map[string]*Build)
  130. if err := json.Unmarshal([]byte(s), &temp); err != nil {
  131. log.Error("json.Unmarshal(%s) error(%v)", s, err)
  132. return
  133. }
  134. for plat, build := range temp {
  135. p, _ := strconv.Atoi(plat)
  136. builds[p] = build
  137. }
  138. return
  139. }
  140. // TempTaskID gen temporary task ID.
  141. func TempTaskID() string {
  142. n := time.Now().UnixNano()
  143. m := md5.Sum([]byte(strconv.FormatInt(n, 10)))
  144. return TempTaskPrefix + fmt.Sprintf("%x", m)[:8] // 要把taskid当作jobkey参数,jobkey要求长度最多9位, 1位prefix+8位时间hash值前段
  145. }
  146. // JobName gen job name.
  147. func JobName(timestamp int64, content, linkValue, group string) int64 {
  148. s := []byte(fmt.Sprintf("%d%s%s%s%s", timestamp, time.Now().Format("20060102"), content, linkValue, group))
  149. return int64(farm.Hash64(s) % math.MaxInt64)
  150. }
  151. // Hash gen hash value by solt.
  152. func Hash(salt string) string {
  153. s := salt + strconv.FormatInt(time.Now().UnixNano(), 10)
  154. return fmt.Sprintf("%x", md5.Sum([]byte(s)))
  155. }
  156. // 免打扰时间默认值
  157. const (
  158. _defaultSilentBeginHour = 22
  159. _defaultSilentEndHour = 8
  160. _defaultSilentBeginMinute = 0
  161. _defaultSilentEndMinute = 0
  162. )
  163. // ParseSilentTime .
  164. func ParseSilentTime(s string) (st BusinessSilentTime) {
  165. st = BusinessSilentTime{
  166. BeginHour: _defaultSilentBeginHour,
  167. EndHour: _defaultSilentEndHour,
  168. BeginMinute: _defaultSilentBeginMinute,
  169. EndMinute: _defaultSilentEndMinute,
  170. }
  171. s = strings.Trim(s, " ")
  172. if s == "" {
  173. return
  174. }
  175. r := strings.Split(s, "-")
  176. if len(r) != 2 {
  177. return
  178. }
  179. begin := strings.Split(r[0], ":")
  180. if len(begin) == 2 {
  181. st.BeginHour, _ = strconv.Atoi(begin[0])
  182. st.BeginMinute, _ = strconv.Atoi(begin[1])
  183. }
  184. end := strings.Split(r[1], ":")
  185. if len(end) == 2 {
  186. st.EndHour, _ = strconv.Atoi(end[0])
  187. st.EndMinute, _ = strconv.Atoi(end[1])
  188. }
  189. return st
  190. }
  191. // IsAndroid .
  192. func IsAndroid(platformID int) bool {
  193. m := map[int]bool{
  194. PlatformIPhone: true,
  195. PlatformIPad: true,
  196. }
  197. return !m[platformID]
  198. }
  199. // ValidateBuild checks token&platform valid.
  200. func ValidateBuild(platform, build int, builds map[int]*Build) bool {
  201. if len(builds) == 0 {
  202. return true
  203. }
  204. if IsAndroid(platform) {
  205. platform = PlatformAndroid
  206. }
  207. if builds[platform] == nil {
  208. return true
  209. }
  210. c := builds[platform].Condition
  211. b := builds[platform].Build
  212. switch c {
  213. case "gt":
  214. return build > b
  215. case "gte":
  216. return build >= b
  217. case "lt":
  218. return build < b
  219. case "lte":
  220. return build <= b
  221. case "eq":
  222. return build == b
  223. case "ne":
  224. return build != b
  225. }
  226. return false
  227. }