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

tool.go 9.5 kB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package base
  5. import (
  6. "bytes"
  7. "crypto/md5"
  8. "crypto/rand"
  9. "crypto/sha1"
  10. "encoding/hex"
  11. "encoding/json"
  12. "fmt"
  13. "math"
  14. "strings"
  15. "time"
  16. )
  17. // Encode string to md5 hex value
  18. func EncodeMd5(str string) string {
  19. m := md5.New()
  20. m.Write([]byte(str))
  21. return hex.EncodeToString(m.Sum(nil))
  22. }
  23. // Random generate string
  24. func GetRandomString(n int) string {
  25. const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
  26. var bytes = make([]byte, n)
  27. rand.Read(bytes)
  28. for i, b := range bytes {
  29. bytes[i] = alphanum[b%byte(len(alphanum))]
  30. }
  31. return string(bytes)
  32. }
  33. // create a time limit code
  34. // code format: 12 length date time string + 6 minutes string + 40 sha1 encoded string
  35. func CreateTimeLimitCode(data string, minutes int, startInf interface{}) string {
  36. format := "YmdHi"
  37. var start, end time.Time
  38. var startStr, endStr string
  39. if startInf == nil {
  40. // Use now time create code
  41. start = time.Now()
  42. startStr = DateFormat(start, format)
  43. } else {
  44. // use start string create code
  45. startStr = startInf.(string)
  46. start, _ = DateParse(startStr, format)
  47. startStr = DateFormat(start, format)
  48. }
  49. end = start.Add(time.Minute * time.Duration(minutes))
  50. endStr = DateFormat(end, format)
  51. // create sha1 encode string
  52. sh := sha1.New()
  53. sh.Write([]byte(data + SecretKey + startStr + endStr + fmt.Sprintf("%d", minutes)))
  54. encoded := hex.EncodeToString(sh.Sum(nil))
  55. code := fmt.Sprintf("%s%06d%s", startStr, minutes, encoded)
  56. return code
  57. }
  58. func RenderTemplate(TplNames string, Data map[interface{}]interface{}) string {
  59. // if beego.RunMode == "dev" {
  60. // beego.BuildTemplate(beego.ViewsPath)
  61. // }
  62. // ibytes := bytes.NewBufferString("")
  63. // if _, ok := beego.BeeTemplates[TplNames]; !ok {
  64. // panic("can't find templatefile in the path:" + TplNames)
  65. // }
  66. // err := beego.BeeTemplates[TplNames].ExecuteTemplate(ibytes, TplNames, Data)
  67. // if err != nil {
  68. // beego.Trace("template Execute err:", err)
  69. // }
  70. // icontent, _ := ioutil.ReadAll(ibytes)
  71. // return string(icontent)
  72. return "not implement yet"
  73. }
  74. // AvatarLink returns avatar link by given e-mail.
  75. func AvatarLink(email string) string {
  76. return "http://1.gravatar.com/avatar/" + EncodeMd5(email)
  77. }
  78. // Seconds-based time units
  79. const (
  80. Minute = 60
  81. Hour = 60 * Minute
  82. Day = 24 * Hour
  83. Week = 7 * Day
  84. Month = 30 * Day
  85. Year = 12 * Month
  86. )
  87. // TimeSince calculates the time interval and generate user-friendly string.
  88. func TimeSince(then time.Time) string {
  89. now := time.Now()
  90. lbl := "ago"
  91. diff := now.Unix() - then.Unix()
  92. if then.After(now) {
  93. lbl = "from now"
  94. diff = then.Unix() - now.Unix()
  95. }
  96. switch {
  97. case diff <= 0:
  98. return "now"
  99. case diff <= 2:
  100. return fmt.Sprintf("1 second %s", lbl)
  101. case diff < 1*Minute:
  102. return fmt.Sprintf("%d seconds %s", diff, lbl)
  103. case diff < 2*Minute:
  104. return fmt.Sprintf("1 minute %s", lbl)
  105. case diff < 1*Hour:
  106. return fmt.Sprintf("%d minutes %s", diff/Minute, lbl)
  107. case diff < 2*Hour:
  108. return fmt.Sprintf("1 hour %s", lbl)
  109. case diff < 1*Day:
  110. return fmt.Sprintf("%d hours %s", diff/Hour, lbl)
  111. case diff < 2*Day:
  112. return fmt.Sprintf("1 day %s", lbl)
  113. case diff < 1*Week:
  114. return fmt.Sprintf("%d days %s", diff/Day, lbl)
  115. case diff < 2*Week:
  116. return fmt.Sprintf("1 week %s", lbl)
  117. case diff < 1*Month:
  118. return fmt.Sprintf("%d weeks %s", diff/Week, lbl)
  119. case diff < 2*Month:
  120. return fmt.Sprintf("1 month %s", lbl)
  121. case diff < 1*Year:
  122. return fmt.Sprintf("%d months %s", diff/Month, lbl)
  123. case diff < 18*Month:
  124. return fmt.Sprintf("1 year %s", lbl)
  125. }
  126. return then.String()
  127. }
  128. const (
  129. Byte = 1
  130. KByte = Byte * 1024
  131. MByte = KByte * 1024
  132. GByte = MByte * 1024
  133. TByte = GByte * 1024
  134. PByte = TByte * 1024
  135. EByte = PByte * 1024
  136. )
  137. var bytesSizeTable = map[string]uint64{
  138. "b": Byte,
  139. "kb": KByte,
  140. "mb": MByte,
  141. "gb": GByte,
  142. "tb": TByte,
  143. "pb": PByte,
  144. "eb": EByte,
  145. }
  146. func logn(n, b float64) float64 {
  147. return math.Log(n) / math.Log(b)
  148. }
  149. func humanateBytes(s uint64, base float64, sizes []string) string {
  150. if s < 10 {
  151. return fmt.Sprintf("%dB", s)
  152. }
  153. e := math.Floor(logn(float64(s), base))
  154. suffix := sizes[int(e)]
  155. val := float64(s) / math.Pow(base, math.Floor(e))
  156. f := "%.0f"
  157. if val < 10 {
  158. f = "%.1f"
  159. }
  160. return fmt.Sprintf(f+"%s", val, suffix)
  161. }
  162. // FileSize calculates the file size and generate user-friendly string.
  163. func FileSize(s int64) string {
  164. sizes := []string{"B", "KB", "MB", "GB", "TB", "PB", "EB"}
  165. return humanateBytes(uint64(s), 1024, sizes)
  166. }
  167. // Subtract deals with subtraction of all types of number.
  168. func Subtract(left interface{}, right interface{}) interface{} {
  169. var rleft, rright int64
  170. var fleft, fright float64
  171. var isInt bool = true
  172. switch left.(type) {
  173. case int:
  174. rleft = int64(left.(int))
  175. case int8:
  176. rleft = int64(left.(int8))
  177. case int16:
  178. rleft = int64(left.(int16))
  179. case int32:
  180. rleft = int64(left.(int32))
  181. case int64:
  182. rleft = left.(int64)
  183. case float32:
  184. fleft = float64(left.(float32))
  185. isInt = false
  186. case float64:
  187. fleft = left.(float64)
  188. isInt = false
  189. }
  190. switch right.(type) {
  191. case int:
  192. rright = int64(right.(int))
  193. case int8:
  194. rright = int64(right.(int8))
  195. case int16:
  196. rright = int64(right.(int16))
  197. case int32:
  198. rright = int64(right.(int32))
  199. case int64:
  200. rright = right.(int64)
  201. case float32:
  202. fright = float64(left.(float32))
  203. isInt = false
  204. case float64:
  205. fleft = left.(float64)
  206. isInt = false
  207. }
  208. if isInt {
  209. return rleft - rright
  210. } else {
  211. return fleft + float64(rleft) - (fright + float64(rright))
  212. }
  213. }
  214. // DateFormat pattern rules.
  215. var datePatterns = []string{
  216. // year
  217. "Y", "2006", // A full numeric representation of a year, 4 digits Examples: 1999 or 2003
  218. "y", "06", //A two digit representation of a year Examples: 99 or 03
  219. // month
  220. "m", "01", // Numeric representation of a month, with leading zeros 01 through 12
  221. "n", "1", // Numeric representation of a month, without leading zeros 1 through 12
  222. "M", "Jan", // A short textual representation of a month, three letters Jan through Dec
  223. "F", "January", // A full textual representation of a month, such as January or March January through December
  224. // day
  225. "d", "02", // Day of the month, 2 digits with leading zeros 01 to 31
  226. "j", "2", // Day of the month without leading zeros 1 to 31
  227. // week
  228. "D", "Mon", // A textual representation of a day, three letters Mon through Sun
  229. "l", "Monday", // A full textual representation of the day of the week Sunday through Saturday
  230. // time
  231. "g", "3", // 12-hour format of an hour without leading zeros 1 through 12
  232. "G", "15", // 24-hour format of an hour without leading zeros 0 through 23
  233. "h", "03", // 12-hour format of an hour with leading zeros 01 through 12
  234. "H", "15", // 24-hour format of an hour with leading zeros 00 through 23
  235. "a", "pm", // Lowercase Ante meridiem and Post meridiem am or pm
  236. "A", "PM", // Uppercase Ante meridiem and Post meridiem AM or PM
  237. "i", "04", // Minutes with leading zeros 00 to 59
  238. "s", "05", // Seconds, with leading zeros 00 through 59
  239. // time zone
  240. "T", "MST",
  241. "P", "-07:00",
  242. "O", "-0700",
  243. // RFC 2822
  244. "r", time.RFC1123Z,
  245. }
  246. // Parse Date use PHP time format.
  247. func DateParse(dateString, format string) (time.Time, error) {
  248. replacer := strings.NewReplacer(datePatterns...)
  249. format = replacer.Replace(format)
  250. return time.ParseInLocation(format, dateString, time.Local)
  251. }
  252. // Date takes a PHP like date func to Go's time format.
  253. func DateFormat(t time.Time, format string) string {
  254. replacer := strings.NewReplacer(datePatterns...)
  255. format = replacer.Replace(format)
  256. return t.Format(format)
  257. }
  258. type Actioner interface {
  259. GetOpType() int
  260. GetActUserName() string
  261. GetRepoName() string
  262. GetContent() string
  263. }
  264. // ActionIcon accepts a int that represents action operation type
  265. // and returns a icon class name.
  266. func ActionIcon(opType int) string {
  267. switch opType {
  268. case 1: // Create repository.
  269. return "plus-circle"
  270. case 5: // Commit repository.
  271. return "arrow-circle-o-right"
  272. default:
  273. return "invalid type"
  274. }
  275. }
  276. const (
  277. TPL_CREATE_REPO = `<a href="/user/%s">%s</a> created repository <a href="/%s/%s">%s</a>`
  278. TPL_COMMIT_REPO = `<a href="/user/%s">%s</a> pushed to <a href="/%s/%s/tree/%s">%s</a> at <a href="/%s/%s">%s/%s</a>%s`
  279. TPL_COMMIT_REPO_LI = `<div><img id="gogs-user-avatar-commit" src="%s?s=16" alt="user-avatar" title="username"/> <a href="/%s/%s/commit/%s">%s</a> %s</div>`
  280. )
  281. // ActionDesc accepts int that represents action operation type
  282. // and returns the description.
  283. func ActionDesc(act Actioner, avatarLink string) string {
  284. actUserName := act.GetActUserName()
  285. repoName := act.GetRepoName()
  286. content := act.GetContent()
  287. switch act.GetOpType() {
  288. case 1: // Create repository.
  289. return fmt.Sprintf(TPL_CREATE_REPO, actUserName, actUserName, actUserName, repoName, repoName)
  290. case 5: // Commit repository.
  291. var commits [][]string
  292. if err := json.Unmarshal([]byte(content), &commits); err != nil {
  293. return err.Error()
  294. }
  295. buf := bytes.NewBuffer([]byte("\n"))
  296. for _, commit := range commits {
  297. buf.WriteString(fmt.Sprintf(TPL_COMMIT_REPO_LI, avatarLink, actUserName, repoName, commit[0], commit[0][:7], commit[1]) + "\n")
  298. }
  299. return fmt.Sprintf(TPL_COMMIT_REPO, actUserName, actUserName, actUserName, repoName, "master", "master", actUserName, repoName, actUserName, repoName,
  300. buf.String())
  301. default:
  302. return "invalid type"
  303. }
  304. }