| | package common |
| |
|
| | import ( |
| | "bytes" |
| | "context" |
| | crand "crypto/rand" |
| | "encoding/base64" |
| | "encoding/json" |
| | "fmt" |
| | "html/template" |
| | "io" |
| | "log" |
| | "math/big" |
| | "math/rand" |
| | "net" |
| | "os" |
| | "os/exec" |
| | "runtime" |
| | "strconv" |
| | "strings" |
| | "time" |
| |
|
| | "github.com/google/uuid" |
| | "github.com/pkg/errors" |
| | ) |
| |
|
| | func OpenBrowser(url string) { |
| | var err error |
| |
|
| | switch runtime.GOOS { |
| | case "linux": |
| | err = exec.Command("xdg-open", url).Start() |
| | case "windows": |
| | err = exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start() |
| | case "darwin": |
| | err = exec.Command("open", url).Start() |
| | } |
| | if err != nil { |
| | log.Println(err) |
| | } |
| | } |
| |
|
| | func GetIp() (ip string) { |
| | ips, err := net.InterfaceAddrs() |
| | if err != nil { |
| | log.Println(err) |
| | return ip |
| | } |
| |
|
| | for _, a := range ips { |
| | if ipNet, ok := a.(*net.IPNet); ok && !ipNet.IP.IsLoopback() { |
| | if ipNet.IP.To4() != nil { |
| | ip = ipNet.IP.String() |
| | if strings.HasPrefix(ip, "10") { |
| | return |
| | } |
| | if strings.HasPrefix(ip, "172") { |
| | return |
| | } |
| | if strings.HasPrefix(ip, "192.168") { |
| | return |
| | } |
| | ip = "" |
| | } |
| | } |
| | } |
| | return |
| | } |
| |
|
| | var sizeKB = 1024 |
| | var sizeMB = sizeKB * 1024 |
| | var sizeGB = sizeMB * 1024 |
| |
|
| | func Bytes2Size(num int64) string { |
| | numStr := "" |
| | unit := "B" |
| | if num/int64(sizeGB) > 1 { |
| | numStr = fmt.Sprintf("%.2f", float64(num)/float64(sizeGB)) |
| | unit = "GB" |
| | } else if num/int64(sizeMB) > 1 { |
| | numStr = fmt.Sprintf("%d", int(float64(num)/float64(sizeMB))) |
| | unit = "MB" |
| | } else if num/int64(sizeKB) > 1 { |
| | numStr = fmt.Sprintf("%d", int(float64(num)/float64(sizeKB))) |
| | unit = "KB" |
| | } else { |
| | numStr = fmt.Sprintf("%d", num) |
| | } |
| | return numStr + " " + unit |
| | } |
| |
|
| | func Seconds2Time(num int) (time string) { |
| | if num/31104000 > 0 { |
| | time += strconv.Itoa(num/31104000) + " 年 " |
| | num %= 31104000 |
| | } |
| | if num/2592000 > 0 { |
| | time += strconv.Itoa(num/2592000) + " 个月 " |
| | num %= 2592000 |
| | } |
| | if num/86400 > 0 { |
| | time += strconv.Itoa(num/86400) + " 天 " |
| | num %= 86400 |
| | } |
| | if num/3600 > 0 { |
| | time += strconv.Itoa(num/3600) + " 小时 " |
| | num %= 3600 |
| | } |
| | if num/60 > 0 { |
| | time += strconv.Itoa(num/60) + " 分钟 " |
| | num %= 60 |
| | } |
| | time += strconv.Itoa(num) + " 秒" |
| | return |
| | } |
| |
|
| | func Interface2String(inter interface{}) string { |
| | switch inter.(type) { |
| | case string: |
| | return inter.(string) |
| | case int: |
| | return fmt.Sprintf("%d", inter.(int)) |
| | case float64: |
| | return fmt.Sprintf("%f", inter.(float64)) |
| | } |
| | return "Not Implemented" |
| | } |
| |
|
| | func UnescapeHTML(x string) interface{} { |
| | return template.HTML(x) |
| | } |
| |
|
| | func IntMax(a int, b int) int { |
| | if a >= b { |
| | return a |
| | } else { |
| | return b |
| | } |
| | } |
| |
|
| | func IsIP(s string) bool { |
| | ip := net.ParseIP(s) |
| | return ip != nil |
| | } |
| |
|
| | func GetUUID() string { |
| | code := uuid.New().String() |
| | code = strings.Replace(code, "-", "", -1) |
| | return code |
| | } |
| |
|
| | const keyChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" |
| |
|
| | func init() { |
| | rand.New(rand.NewSource(time.Now().UnixNano())) |
| | } |
| |
|
| | func GenerateRandomCharsKey(length int) (string, error) { |
| | b := make([]byte, length) |
| | maxI := big.NewInt(int64(len(keyChars))) |
| |
|
| | for i := range b { |
| | n, err := crand.Int(crand.Reader, maxI) |
| | if err != nil { |
| | return "", err |
| | } |
| | b[i] = keyChars[n.Int64()] |
| | } |
| |
|
| | return string(b), nil |
| | } |
| |
|
| | func GenerateRandomKey(length int) (string, error) { |
| | bytes := make([]byte, length*3/4) |
| | if _, err := crand.Read(bytes); err != nil { |
| | return "", err |
| | } |
| | return base64.StdEncoding.EncodeToString(bytes), nil |
| | } |
| |
|
| | func GenerateKey() (string, error) { |
| | |
| | return GenerateRandomCharsKey(48) |
| | } |
| |
|
| | func GetRandomInt(max int) int { |
| | |
| | return rand.Intn(max) |
| | } |
| |
|
| | func GetTimestamp() int64 { |
| | return time.Now().Unix() |
| | } |
| |
|
| | func GetTimeString() string { |
| | now := time.Now() |
| | return fmt.Sprintf("%s%d", now.Format("20060102150405"), now.UnixNano()%1e9) |
| | } |
| |
|
| | func Max(a int, b int) int { |
| | if a >= b { |
| | return a |
| | } else { |
| | return b |
| | } |
| | } |
| |
|
| | func MessageWithRequestId(message string, id string) string { |
| | return fmt.Sprintf("%s (request id: %s)", message, id) |
| | } |
| |
|
| | func RandomSleep() { |
| | |
| | time.Sleep(time.Duration(rand.Intn(3000)) * time.Millisecond) |
| | } |
| |
|
| | func GetPointer[T any](v T) *T { |
| | return &v |
| | } |
| |
|
| | func Any2Type[T any](data any) (T, error) { |
| | var zero T |
| | bytes, err := json.Marshal(data) |
| | if err != nil { |
| | return zero, err |
| | } |
| | var res T |
| | err = json.Unmarshal(bytes, &res) |
| | if err != nil { |
| | return zero, err |
| | } |
| | return res, nil |
| | } |
| |
|
| | |
| | func SaveTmpFile(filename string, data io.Reader) (string, error) { |
| | f, err := os.CreateTemp(os.TempDir(), filename) |
| | if err != nil { |
| | return "", errors.Wrapf(err, "failed to create temporary file %s", filename) |
| | } |
| | defer f.Close() |
| |
|
| | _, err = io.Copy(f, data) |
| | if err != nil { |
| | return "", errors.Wrapf(err, "failed to copy data to temporary file %s", filename) |
| | } |
| |
|
| | return f.Name(), nil |
| | } |
| |
|
| | |
| | func GetAudioDuration(ctx context.Context, filename string) (float64, error) { |
| | |
| | c := exec.CommandContext(ctx, "ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", filename) |
| | output, err := c.Output() |
| | if err != nil { |
| | return 0, errors.Wrap(err, "failed to get audio duration") |
| | } |
| |
|
| | return strconv.ParseFloat(string(bytes.TrimSpace(output)), 64) |
| | } |
| |
|