Files
jx-print/utils/utils.go
2021-07-22 17:07:26 +08:00

254 lines
6.5 KiB
Go

package utils
import (
"bytes"
"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/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{}{},
}
)
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
}