package putils import ( "bytes" "crypto/md5" "encoding/json" "fmt" "git.rosy.net.cn/baseapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-print/globals" "git.rosy.net.cn/jx-print/model" "github.com/dchest/captcha" "github.com/gin-gonic/gin" "math" "math/rand" "net/http" "strings" "time" ) var commonInitialisms = []string{"ACL", "API", "ASCII", "CPU", "CSS", "DNS", "EOF", "GUID", "HTML", "HTTP", "HTTPS", "ID", "IP", "JSON", "LHS", "QPS", "RAM", "RHS", "RPC", "SLA", "SMTP", "SQL", "SSH", "TCP", "TLS", "TTL", "UDP", "UI", "UID", "UUID", "URI", "URL", "UTF8", "VM", "XML", "XMPP", "XSRF", "XSS"} var commonInitialismsReplacer *strings.Replacer var uncommonInitialismsReplacer *strings.Replacer func init() { var commonInitialismsForReplacer []string var uncommonInitialismsForReplacer []string for _, initialism := range commonInitialisms { commonInitialismsForReplacer = append(commonInitialismsForReplacer, initialism, strings.Title(strings.ToLower(initialism))) uncommonInitialismsForReplacer = append(uncommonInitialismsForReplacer, strings.Title(strings.ToLower(initialism)), initialism) } commonInitialismsReplacer = strings.NewReplacer(commonInitialismsForReplacer...) uncommonInitialismsReplacer = strings.NewReplacer(uncommonInitialismsForReplacer...) } var ( letterBytes = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" letterBytesNum = "0123456789" flowUnitMap = map[string]struct{}{ "KB": struct{}{}, "MB": struct{}{}, "GB": struct{}{}, } orderNoBeginTimestamp = utils.Str2Time("2010-01-01 00:00:00").Unix() ) func RandStringBytes(n int) string { b := make([]byte, n) for i := range b { b[i] = letterBytes[rand.Intn(len(letterBytes))] } return string(b) } func RandStringBytesWithNumber(n int) string { b := make([]byte, n) for i := range b { b[i] = letterBytesNum[rand.Intn(len(letterBytesNum))] } return string(b) } func Captcha(c *gin.Context, length ...int) { l := captcha.DefaultLen w, h := 107, 36 if len(length) == 1 { l = length[0] } if len(length) == 2 { w = length[1] } if len(length) == 3 { h = length[2] } captchaId := captcha.NewLen(l) //session := sessions.Default(c) //session.Set(c.ClientIP()+model.SessionKey, captchaId) //_ = session.Save() if err := SetKey(c.ClientIP()+model.SessionKey, captchaId, time.Minute*5); err == nil { _ = Serve(c.Writer, c.Request, captchaId, ".png", "zh", false, w, h) } } func Serve(w http.ResponseWriter, r *http.Request, id, ext, lang string, download bool, width, height int) error { w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") w.Header().Set("Pragma", "no-cache") w.Header().Set("Expires", "0") var content bytes.Buffer switch ext { case ".png": w.Header().Set("Content-Type", "image/png") _ = captcha.WriteImage(&content, id, width, height) case ".wav": w.Header().Set("Content-Type", "audio/x-wav") _ = captcha.WriteAudio(&content, id, lang) default: return captcha.ErrNotFound } if download { w.Header().Set("Content-Type", "application/octet-stream") } http.ServeContent(w, r, id+ext, time.Time{}, bytes.NewReader(content.Bytes())) return nil } //驼峰转下划线 func UnMarshalHr(name string) string { const ( lower = false upper = true ) if name == "" { return "" } var ( value = commonInitialismsReplacer.Replace(name) buf = bytes.NewBufferString("") lastCase, currCase, nextCase, nextNumber bool ) for i, v := range value[:len(value)-1] { nextCase = bool(value[i+1] >= 'A' && value[i+1] <= 'Z') nextNumber = bool(value[i+1] >= '0' && value[i+1] <= '9') if i > 0 { if currCase == upper { if lastCase == upper && (nextCase == upper || nextNumber == upper) { buf.WriteRune(v) } else { if value[i-1] != '_' && value[i+1] != '_' { buf.WriteRune('_') } buf.WriteRune(v) } } else { buf.WriteRune(v) if i == len(value)-2 && (nextCase == upper && nextNumber == lower) { buf.WriteRune('_') } } } else { currCase = upper buf.WriteRune(v) } lastCase = currCase currCase = nextCase } buf.WriteByte(value[len(value)-1]) s := strings.ToLower(buf.String()) return s } func UnmarshalUseNumber(data []byte, result interface{}) error { err := TryUnmarshalUseNumber(data, result) if err != nil { globals.SugarLogger.Infof("decode data:%v, error:%v", string(data), err) } return err } func TryUnmarshalUseNumber(data []byte, result interface{}) error { d := json.NewDecoder(bytes.NewReader(data)) d.UseNumber() return d.Decode(result) } func BuildErr(errs []error) (err error) { var errStr = strings.Builder{} for _, v := range errs { errStr.WriteString(v.Error()) } return fmt.Errorf(errStr.String()) } func Format4Output(obj interface{}, isSingleLine bool) (retVal string) { retVal, ok := obj.(string) if !ok { var ( result []byte err error ) if isSingleLine { if result, err = json.Marshal(obj); err == nil { retVal = string(result) } } else { if result, err = json.MarshalIndent(obj, "", "\t"); err == nil { retVal = string(result) } } if err != nil { baseapi.SugarLogger.Infof("Format4Output Marshal:%v failed with error:%v", obj, err) retVal = fmt.Sprintf("%v", obj) } } return retVal } func GetNextTimeFromList(now time.Time, timeList []string) (snapshotAt time.Time) { dateStr := utils.Time2DateStr(now) timeListLen := len(timeList) selectTime := utils.Str2Time(utils.Time2DateStr(now.Add(24*time.Hour)) + " " + timeList[0]) for k := range timeList { v := timeList[timeListLen-k-1] tmpTime := utils.Str2Time(dateStr + " " + v) if tmpTime.Sub(now) < 0 { break } selectTime = tmpTime } return selectTime } func SplitFlowAndUnit(flowStr string) (flow float64, unit string) { for k, _ := range flowUnitMap { if strings.Contains(flowStr, k) { return utils.Str2Float64WithDefault(flowStr[:len(flowStr)-2], 0), flowStr[len(flowStr)-2:] } } return flow, unit } func Flow2KB(flow float64, unit string) (flowKB float64) { if unit == "KB" { return flow } else if unit == "MB" { return flow * float64(1024) } else if unit == "GB" { return flow * float64(1024) * float64(1024) } return flowKB } func FlowKB2Other(flowKB float64) (flow float64, unit string) { if flowKB < 1024 { return flowKB, "KB" } else { flowMB := utils.Str2Float64(fmt.Sprintf("%.2f", flowKB/float64(1024))) if flowMB < 1024 { return flowMB, "MB" } else { flowGB := utils.Str2Float64(fmt.Sprintf("%.2f", flowMB/float64(1024))) if flowGB < 1024 { return flowGB, "GB" } } } return flow, unit } func GenOrderNo() (orderNo int64) { var prefix = utils.Str2Int64(time.Now().Format("20060102")) const randPartNum = 1000 orderNo = time.Now().Unix() - orderNoBeginTimestamp orderNo = orderNo * randPartNum md5Bytes := md5.Sum([]byte(utils.GetUUID())) randPart := 0 for k, v := range md5Bytes { randPart += int(v) << ((k % 3) * 8) } orderNo += int64(randPart % randPartNum) orderNo += int64(math.Pow10(int(math.Log10(float64(orderNo)))+1)) * prefix return orderNo }