github.com/kotovmak/go-admin@v1.1.1/modules/utils/utils.go (about) 1 package utils 2 3 import ( 4 "archive/zip" 5 "bytes" 6 "encoding/gob" 7 "encoding/json" 8 "fmt" 9 "html/template" 10 "io" 11 "math" 12 "net/http" 13 "net/url" 14 "os" 15 "path/filepath" 16 "reflect" 17 "regexp" 18 "strconv" 19 "strings" 20 textTmpl "text/template" 21 "time" 22 23 "github.com/NebulousLabs/fastrand" 24 ) 25 26 func Uuid(length int64) string { 27 ele := []string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "v", "k", 28 "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "Driver", "E", "F", "G", 29 "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"} 30 ele, _ = Random(ele) 31 uuid := "" 32 var i int64 33 for i = 0; i < length; i++ { 34 uuid += ele[fastrand.Intn(59)] 35 } 36 return uuid 37 } 38 39 func Random(strings []string) ([]string, error) { 40 for i := len(strings) - 1; i > 0; i-- { 41 num := fastrand.Intn(i + 1) 42 strings[i], strings[num] = strings[num], strings[i] 43 } 44 45 str := make([]string, 0) 46 for i := 0; i < len(strings); i++ { 47 str = append(str, strings[i]) 48 } 49 return str, nil 50 } 51 52 func CompressedContent(h *template.HTML) { 53 st := strings.Split(string(*h), "\n") 54 var ss []string 55 for i := 0; i < len(st); i++ { 56 st[i] = strings.TrimSpace(st[i]) 57 if st[i] != "" { 58 ss = append(ss, st[i]) 59 } 60 } 61 *h = template.HTML(strings.Join(ss, "\n")) 62 } 63 64 func ReplaceNth(s, old, new string, n int) string { 65 i := 0 66 for m := 1; m <= n; m++ { 67 x := strings.Index(s[i:], old) 68 if x < 0 { 69 break 70 } 71 i += x 72 if m == n { 73 return s[:i] + new + s[i+len(old):] 74 } 75 i += len(old) 76 } 77 return s 78 } 79 80 func InArray(arr []string, str string) bool { 81 for _, v := range arr { 82 if v == str { 83 return true 84 } 85 } 86 return false 87 } 88 89 func WrapURL(u string) string { 90 uarr := strings.Split(u, "?") 91 if len(uarr) < 2 { 92 return url.QueryEscape(strings.ReplaceAll(u, "/", "_")) 93 } 94 v, err := url.ParseQuery(uarr[1]) 95 if err != nil { 96 return url.QueryEscape(strings.ReplaceAll(u, "/", "_")) 97 } 98 return url.QueryEscape(strings.ReplaceAll(uarr[0], "/", "_")) + "?" + 99 strings.ReplaceAll(v.Encode(), "%7B%7B.Id%7D%7D", "{{.Id}}") 100 } 101 102 func JSON(a interface{}) string { 103 if a == nil { 104 return "" 105 } 106 b, _ := json.Marshal(a) 107 return string(b) 108 } 109 110 func ParseBool(s string) bool { 111 b1, _ := strconv.ParseBool(s) 112 return b1 113 } 114 115 func ReplaceAll(s string, oldnew ...string) string { 116 repl := strings.NewReplacer(oldnew...) 117 return repl.Replace(s) 118 } 119 120 func PackageName(v interface{}) string { 121 if v == nil { 122 return "" 123 } 124 125 val := reflect.ValueOf(v) 126 if val.Kind() == reflect.Ptr { 127 return val.Elem().Type().PkgPath() 128 } 129 return val.Type().PkgPath() 130 } 131 132 func ParseFloat32(f string) float32 { 133 s, _ := strconv.ParseFloat(f, 32) 134 return float32(s) 135 } 136 137 func SetDefault(value, condition, def string) string { 138 if value == condition { 139 return def 140 } 141 return value 142 } 143 144 func AorB(condition bool, a, b string) string { 145 if condition { 146 return a 147 } 148 return b 149 } 150 151 func IsJSON(str string) bool { 152 var js json.RawMessage 153 return json.Unmarshal([]byte(str), &js) == nil 154 } 155 156 func CopyMap(m map[string]string) map[string]string { 157 var buf bytes.Buffer 158 enc := gob.NewEncoder(&buf) 159 dec := gob.NewDecoder(&buf) 160 err := enc.Encode(m) 161 if err != nil { 162 panic(err) 163 } 164 var cm map[string]string 165 err = dec.Decode(&cm) 166 if err != nil { 167 panic(err) 168 } 169 return cm 170 } 171 172 func ParseTime(stringTime string) time.Time { 173 loc, _ := time.LoadLocation("Local") 174 theTime, _ := time.ParseInLocation("2006-01-02 15:04:05", stringTime, loc) 175 return theTime 176 } 177 178 func ParseHTML(name, tmpl string, param interface{}) template.HTML { 179 t := template.New(name) 180 t, err := t.Parse(tmpl) 181 if err != nil { 182 fmt.Println("utils parseHTML error", err) 183 return "" 184 } 185 buf := new(bytes.Buffer) 186 err = t.Execute(buf, param) 187 if err != nil { 188 fmt.Println("utils parseHTML error", err) 189 return "" 190 } 191 return template.HTML(buf.String()) 192 } 193 194 func ParseText(name, tmpl string, param interface{}) string { 195 t := textTmpl.New(name) 196 t, err := t.Parse(tmpl) 197 if err != nil { 198 fmt.Println("utils parseHTML error", err) 199 return "" 200 } 201 buf := new(bytes.Buffer) 202 err = t.Execute(buf, param) 203 if err != nil { 204 fmt.Println("utils parseHTML error", err) 205 return "" 206 } 207 return buf.String() 208 } 209 210 func CompareVersion(src, toCompare string) bool { 211 if toCompare == "" { 212 return false 213 } 214 215 exp, _ := regexp.Compile(`-(.*)`) 216 src = exp.ReplaceAllString(src, "") 217 toCompare = exp.ReplaceAllString(toCompare, "") 218 219 srcs := strings.Split(src, "v") 220 srcArr := strings.Split(srcs[1], ".") 221 op := ">" 222 srcs[0] = strings.TrimSpace(srcs[0]) 223 if InArray([]string{">=", "<=", "=", ">", "<"}, srcs[0]) { 224 op = srcs[0] 225 } 226 227 toCompare = strings.ReplaceAll(toCompare, "v", "") 228 229 if op == "=" { 230 return srcs[1] == toCompare 231 } 232 233 if srcs[1] == toCompare && (op == "<=" || op == ">=") { 234 return true 235 } 236 237 toCompareArr := strings.Split(strings.ReplaceAll(toCompare, "v", ""), ".") 238 for i := 0; i < len(srcArr); i++ { 239 v, err := strconv.Atoi(srcArr[i]) 240 if err != nil { 241 return false 242 } 243 vv, err := strconv.Atoi(toCompareArr[i]) 244 if err != nil { 245 return false 246 } 247 switch op { 248 case ">", ">=": 249 if v < vv { 250 return true 251 } else if v > vv { 252 return false 253 } else { 254 continue 255 } 256 case "<", "<=": 257 if v > vv { 258 return true 259 } else if v < vv { 260 return false 261 } else { 262 continue 263 } 264 } 265 } 266 267 return false 268 } 269 270 const ( 271 Byte = 1 272 KByte = Byte * 1024 273 MByte = KByte * 1024 274 GByte = MByte * 1024 275 TByte = GByte * 1024 276 PByte = TByte * 1024 277 EByte = PByte * 1024 278 ) 279 280 func logn(n, b float64) float64 { 281 return math.Log(n) / math.Log(b) 282 } 283 284 func humanateBytes(s uint64, base float64, sizes []string) string { 285 if s < 10 { 286 return fmt.Sprintf("%d B", s) 287 } 288 e := math.Floor(logn(float64(s), base)) 289 suffix := sizes[int(e)] 290 val := float64(s) / math.Pow(base, math.Floor(e)) 291 f := "%.0f" 292 if val < 10 { 293 f = "%.1f" 294 } 295 296 return fmt.Sprintf(f+" %s", val, suffix) 297 } 298 299 // FileSize calculates the file size and generate user-friendly string. 300 func FileSize(s uint64) string { 301 sizes := []string{"B", "KB", "MB", "GB", "TB", "PB", "EB"} 302 return humanateBytes(s, 1024, sizes) 303 } 304 305 func FileExist(path string) bool { 306 _, err := os.Stat(path) 307 if err != nil { 308 return os.IsExist(err) 309 } 310 return true 311 } 312 313 // TimeSincePro calculates the time interval and generate full user-friendly string. 314 func TimeSincePro(then time.Time, m map[string]string) string { 315 now := time.Now() 316 diff := now.Unix() - then.Unix() 317 318 if then.After(now) { 319 return "future" 320 } 321 322 var timeStr, diffStr string 323 for { 324 if diff == 0 { 325 break 326 } 327 328 diff, diffStr = computeTimeDiff(diff, m) 329 timeStr += ", " + diffStr 330 } 331 return strings.TrimPrefix(timeStr, ", ") 332 } 333 334 // Seconds-based time units 335 const ( 336 Minute = 60 337 Hour = 60 * Minute 338 Day = 24 * Hour 339 Week = 7 * Day 340 Month = 30 * Day 341 Year = 12 * Month 342 ) 343 344 func computeTimeDiff(diff int64, m map[string]string) (int64, string) { 345 diffStr := "" 346 switch { 347 case diff <= 0: 348 diff = 0 349 diffStr = "now" 350 case diff < 2: 351 diff = 0 352 diffStr = "1 " + m["second"] 353 case diff < 1*Minute: 354 diffStr = fmt.Sprintf("%d "+m["seconds"], diff) 355 diff = 0 356 357 case diff < 2*Minute: 358 diff -= 1 * Minute 359 diffStr = "1 " + m["minute"] 360 case diff < 1*Hour: 361 diffStr = fmt.Sprintf("%d "+m["minutes"], diff/Minute) 362 diff -= diff / Minute * Minute 363 364 case diff < 2*Hour: 365 diff -= 1 * Hour 366 diffStr = "1 " + m["hour"] 367 case diff < 1*Day: 368 diffStr = fmt.Sprintf("%d "+m["hours"], diff/Hour) 369 diff -= diff / Hour * Hour 370 371 case diff < 2*Day: 372 diff -= 1 * Day 373 diffStr = "1 " + m["day"] 374 case diff < 1*Week: 375 diffStr = fmt.Sprintf("%d "+m["days"], diff/Day) 376 diff -= diff / Day * Day 377 378 case diff < 2*Week: 379 diff -= 1 * Week 380 diffStr = "1 " + m["week"] 381 case diff < 1*Month: 382 diffStr = fmt.Sprintf("%d "+m["weeks"], diff/Week) 383 diff -= diff / Week * Week 384 385 case diff < 2*Month: 386 diff -= 1 * Month 387 diffStr = "1 " + m["month"] 388 case diff < 1*Year: 389 diffStr = fmt.Sprintf("%d "+m["months"], diff/Month) 390 diff -= diff / Month * Month 391 392 case diff < 2*Year: 393 diff -= 1 * Year 394 diffStr = "1 " + m["year"] 395 default: 396 diffStr = fmt.Sprintf("%d "+m["years"], diff/Year) 397 diff = 0 398 } 399 return diff, diffStr 400 } 401 402 func DownloadTo(url, output string) error { 403 404 req, err := http.NewRequest("GET", url, nil) 405 406 if err != nil { 407 return err 408 } 409 410 res, err := http.DefaultClient.Do(req) 411 412 if err != nil { 413 return err 414 } 415 416 defer func() { 417 _ = res.Body.Close() 418 }() 419 420 file, err := os.Create(output) 421 422 if err != nil { 423 return err 424 } 425 426 _, err = io.Copy(file, res.Body) 427 428 if err != nil { 429 return err 430 } 431 432 return nil 433 } 434 435 func UnzipDir(src, dest string) error { 436 r, err := zip.OpenReader(src) 437 if err != nil { 438 return err 439 } 440 defer func() { 441 if err := r.Close(); err != nil { 442 panic(err) 443 } 444 }() 445 446 err = os.MkdirAll(dest, 0750) 447 448 if err != nil { 449 return err 450 } 451 452 // Closure to address file descriptors issue with all the deferred .Close() methods 453 extractAndWriteFile := func(f *zip.File) error { 454 rc, err := f.Open() 455 if err != nil { 456 return err 457 } 458 defer func() { 459 if err := rc.Close(); err != nil { 460 panic(err) 461 } 462 }() 463 464 path := filepath.Join(dest, f.Name) 465 466 if f.FileInfo().IsDir() { 467 err = os.MkdirAll(path, f.Mode()) 468 if err != nil { 469 return err 470 } 471 } else { 472 err = os.MkdirAll(filepath.Dir(path), f.Mode()) 473 if err != nil { 474 return err 475 } 476 f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) 477 if err != nil { 478 return err 479 } 480 defer func() { 481 if err := f.Close(); err != nil { 482 panic(err) 483 } 484 }() 485 486 _, err = io.Copy(f, rc) 487 if err != nil { 488 return err 489 } 490 } 491 return nil 492 } 493 494 for _, f := range r.File { 495 err := extractAndWriteFile(f) 496 if err != nil { 497 return err 498 } 499 } 500 501 return nil 502 }