feat: omc原始代码
This commit is contained in:
698
lib/global/kits.go
Normal file
698
lib/global/kits.go
Normal file
@@ -0,0 +1,698 @@
|
||||
package global
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
IsIPv4 = "IPv4"
|
||||
IsIPv6 = "IPv6"
|
||||
NonIP = "NonIp"
|
||||
)
|
||||
|
||||
type em struct{}
|
||||
|
||||
func GetPkgName() string {
|
||||
return reflect.TypeOf(em{}).PkgPath()
|
||||
}
|
||||
|
||||
// interface{} change to map[string]interface{}
|
||||
// interface{} data is []interface{}
|
||||
func ListToMap(list interface{}, key string) map[string]interface{} {
|
||||
res := make(map[string]interface{})
|
||||
arr := ToSlice(list)
|
||||
for _, row := range arr {
|
||||
immutable := reflect.ValueOf(row)
|
||||
val := immutable.FieldByName(key).String()
|
||||
res[val] = row
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// interface{} change to []interface{}
|
||||
func ToSlice(arr interface{}) []interface{} {
|
||||
ret := make([]interface{}, 0)
|
||||
v := reflect.ValueOf(arr)
|
||||
if v.Kind() != reflect.Slice {
|
||||
ret = append(ret, arr)
|
||||
return ret
|
||||
}
|
||||
l := v.Len()
|
||||
for i := 0; i < l; i++ {
|
||||
ret = append(ret, v.Index(i).Interface())
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
var TodoList []Todo
|
||||
|
||||
type Todo struct {
|
||||
Id int64
|
||||
Item string
|
||||
}
|
||||
|
||||
// JSON序列化方式
|
||||
func jsonStructToMap(TodoList Todo) (map[string]interface{}, error) {
|
||||
// 结构体转json
|
||||
strRet, err := json.Marshal(TodoList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// json转map
|
||||
var mRet map[string]interface{}
|
||||
err1 := json.Unmarshal(strRet, &mRet)
|
||||
if err1 != nil {
|
||||
return nil, err1
|
||||
}
|
||||
return mRet, nil
|
||||
}
|
||||
|
||||
func IsContain(item string, items []string) bool {
|
||||
for _, e := range items {
|
||||
if e == item {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func IsContainP(item string, items *[]string, size int) bool {
|
||||
for i := 0; i < size; i++ {
|
||||
if (*items)[i] == item {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 将字符串 分割成 字符串数组
|
||||
// @s:分割符
|
||||
func SplitString(str string, s string) []string {
|
||||
sa := strings.Split(str, s)
|
||||
return sa
|
||||
}
|
||||
|
||||
// 合并字符串数组
|
||||
func MergeStringArr(a, b []string) []string {
|
||||
var arr []string
|
||||
for _, i := range a {
|
||||
arr = append(arr, i)
|
||||
}
|
||||
for _, j := range b {
|
||||
arr = append(arr, j)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// 数组去重
|
||||
func UniqueStringArr(m []string) []string {
|
||||
d := make([]string, 0)
|
||||
tempMap := make(map[string]bool, len(m))
|
||||
for _, v := range m { // 以值作为键名
|
||||
if tempMap[v] == false {
|
||||
tempMap[v] = true
|
||||
d = append(d, v)
|
||||
}
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// 合并整型数组
|
||||
func MergeArr(a, b []int) []int {
|
||||
var arr []int
|
||||
for _, i := range a {
|
||||
arr = append(arr, i)
|
||||
}
|
||||
for _, j := range b {
|
||||
arr = append(arr, j)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// 数组去重
|
||||
func UniqueArr(m []int) []int {
|
||||
d := make([]int, 0)
|
||||
tempMap := make(map[int]bool, len(m))
|
||||
for _, v := range m { // 以值作为键名
|
||||
if tempMap[v] == false {
|
||||
tempMap[v] = true
|
||||
d = append(d, v)
|
||||
}
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// 升序
|
||||
func AscArr(e []int) []int {
|
||||
sort.Ints(e[:])
|
||||
return e
|
||||
}
|
||||
|
||||
// 降序
|
||||
func DescArr(e []int) []int {
|
||||
sort.Sort(sort.Reverse(sort.IntSlice(e)))
|
||||
return e
|
||||
}
|
||||
|
||||
func MatchRmUID(p string, s string) bool {
|
||||
match, _ := regexp.MatchString(p, s)
|
||||
return match
|
||||
}
|
||||
|
||||
type OrderedMap struct {
|
||||
Order []string
|
||||
Map map[string]interface{}
|
||||
}
|
||||
|
||||
func (om *OrderedMap) UnmarshalJson(b []byte) error {
|
||||
json.Unmarshal(b, &om.Map)
|
||||
|
||||
index := make(map[string]int)
|
||||
for key := range om.Map {
|
||||
om.Order = append(om.Order, key)
|
||||
esc, _ := json.Marshal(key) //Escape the key
|
||||
index[key] = bytes.Index(b, esc)
|
||||
}
|
||||
|
||||
sort.Slice(om.Order, func(i, j int) bool { return index[om.Order[i]] < index[om.Order[j]] })
|
||||
return nil
|
||||
}
|
||||
|
||||
func (om OrderedMap) MarshalJson() ([]byte, error) {
|
||||
var b []byte
|
||||
buf := bytes.NewBuffer(b)
|
||||
buf.WriteRune('{')
|
||||
l := len(om.Order)
|
||||
for i, key := range om.Order {
|
||||
km, err := json.Marshal(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf.Write(km)
|
||||
buf.WriteRune(':')
|
||||
vm, err := json.Marshal(om.Map[key])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf.Write(vm)
|
||||
if i != l-1 {
|
||||
buf.WriteRune(',')
|
||||
}
|
||||
fmt.Println(buf.String())
|
||||
}
|
||||
buf.WriteRune('}')
|
||||
fmt.Println(buf.String())
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func GetBodyCopy(r *http.Request) (*bytes.Buffer, error) {
|
||||
// If r.bodyBuf present, return the copy
|
||||
// if r.bodyBuf != nil {
|
||||
// return bytes.NewBuffer(r.bodyBuf.Bytes()), nil
|
||||
// }
|
||||
|
||||
// Maybe body is `io.Reader`.
|
||||
// Note: Resty user have to watchout for large body size of `io.Reader`
|
||||
if r.Body != nil {
|
||||
b, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Restore the Body
|
||||
// close(r.Body)
|
||||
r.Body = io.NopCloser(bytes.NewReader(b))
|
||||
|
||||
// Return the Body bytes
|
||||
return bytes.NewBuffer(b), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func UnmarshalBody(r *http.Request, v *interface{}, maxLen int64) error {
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, maxLen))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return json.Unmarshal(body, v)
|
||||
}
|
||||
|
||||
func SetNotifyUrl(ip string, port uint16, uri string) string {
|
||||
return fmt.Sprintf("http://%s:%d%s", ip, port, uri)
|
||||
}
|
||||
|
||||
func GetIps() (ips []string, err error) {
|
||||
interfaceAddr, err := net.InterfaceAddrs()
|
||||
if err != nil {
|
||||
return ips, err
|
||||
}
|
||||
|
||||
for _, address := range interfaceAddr {
|
||||
ipNet, isVailIpNet := address.(*net.IPNet)
|
||||
// 检查ip地址判断是否回环地址
|
||||
if isVailIpNet && !ipNet.IP.IsLoopback() {
|
||||
if ipNet.IP.To4() != nil {
|
||||
ips = append(ips, ipNet.IP.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
return ips, nil
|
||||
}
|
||||
|
||||
func GetCurrentTimeSliceIndexByPeriod(t time.Time, period int) int {
|
||||
index := int((t.Hour()*60+t.Minute())/period) - 1
|
||||
if index < 0 {
|
||||
return int(24*60/period) - 1
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
var (
|
||||
cst *time.Location
|
||||
)
|
||||
|
||||
// RFC3339ToDateTime convert rfc3339 value to china standard time layout
|
||||
func RFC3339ToDateTime(value string) (string, error) {
|
||||
ts, err := time.Parse(time.RFC3339, value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return ts.In(cst).Format("2006-01-02 15:04:05"), nil
|
||||
}
|
||||
|
||||
// CreateTimeDir 根据当前时间格式来创建文件夹
|
||||
func CreateTimeDir(fmt string, path string) string {
|
||||
folderName := time.Now().Format(fmt)
|
||||
folderPath := filepath.Join(path, folderName)
|
||||
if _, err := os.Stat(folderPath); os.IsNotExist(err) {
|
||||
// 必须分成两步:先创建文件夹、再修改权限
|
||||
os.Mkdir(folderPath, 0664) //0644也可以os.ModePerm
|
||||
os.Chmod(folderPath, 0664)
|
||||
}
|
||||
return folderPath
|
||||
}
|
||||
|
||||
// CreateDir 根据传入的目录名和路径来创建文件夹
|
||||
func CreateDir(folderName string, path string) string {
|
||||
folderPath := filepath.Join(path, folderName)
|
||||
if _, err := os.Stat(folderPath); os.IsNotExist(err) {
|
||||
// 必须分成两步:先创建文件夹、再修改权限
|
||||
os.MkdirAll(folderPath, 0664) //0644也可以os.ModePerm
|
||||
os.Chmod(folderPath, 0664)
|
||||
}
|
||||
return folderPath
|
||||
}
|
||||
|
||||
func GetFmtTimeString(srcFmt string, timeString string, dstFmt string) string {
|
||||
t, _ := time.ParseInLocation(srcFmt, timeString, time.Local)
|
||||
return t.Format(dstFmt)
|
||||
}
|
||||
|
||||
func GetFileMD5Sum(filePath string) (string, error) {
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer file.Close()
|
||||
md5 := md5.New()
|
||||
_, err = io.Copy(md5, file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
md5str := hex.EncodeToString(md5.Sum(nil))
|
||||
|
||||
return md5str, nil
|
||||
}
|
||||
|
||||
// PathExists check path is exist or no
|
||||
func PathExists(path string) (bool, error) {
|
||||
_, err := os.Stat(path)
|
||||
if err == nil { //文件或者目录存在
|
||||
return true, nil
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
// PathExists check path is exist or no
|
||||
func FilePathExists(filePath string) (bool, error) {
|
||||
_, err := os.Stat(filePath)
|
||||
if err == nil { //文件或者目录存在
|
||||
return true, nil
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
func GetDayDuration(d1, d2 string) int64 {
|
||||
a, _ := time.Parse("2006-01-02", d1)
|
||||
b, _ := time.Parse("2006-01-02", d2)
|
||||
d := a.Sub(b)
|
||||
|
||||
return (int64)(d.Hours() / 24)
|
||||
}
|
||||
|
||||
func GetSecondsSinceDatetime(datetimeStr string) (int64, error) {
|
||||
loc1, _ := time.LoadLocation("Local")
|
||||
// 解析日期时间字符串为时间对象
|
||||
datetime, err := time.ParseInLocation(time.DateTime, datetimeStr, loc1)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// 计算时间差
|
||||
duration := time.Since(datetime)
|
||||
|
||||
// 获取时间差的秒数
|
||||
seconds := int64(duration.Seconds())
|
||||
|
||||
return seconds, nil
|
||||
}
|
||||
|
||||
func GetSecondDuration(time1, time2 string) (int64, error) {
|
||||
loc1, _ := time.LoadLocation("Local")
|
||||
// 解析日期时间字符串为时间对象
|
||||
t1, err := time.ParseInLocation(time.DateTime, time1, loc1)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
t2, err := time.ParseInLocation(time.DateTime, time2, loc1)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// 计算时间差
|
||||
duration := t2.Sub(t1)
|
||||
|
||||
// 获取时间差的秒数
|
||||
seconds := int64(duration.Seconds())
|
||||
|
||||
return seconds, nil
|
||||
}
|
||||
|
||||
// 0: invalid ip
|
||||
// 4: IPv4
|
||||
// 6: IPv6
|
||||
func ParseIP(s string) (net.IP, int) {
|
||||
ip := net.ParseIP(s)
|
||||
if ip == nil {
|
||||
return nil, 0
|
||||
}
|
||||
for i := 0; i < len(s); i++ {
|
||||
switch s[i] {
|
||||
case '.':
|
||||
return ip, 4
|
||||
case ':':
|
||||
return ip, 6
|
||||
}
|
||||
}
|
||||
return nil, 0
|
||||
}
|
||||
|
||||
func BytesCombine1(pBytes ...[]byte) []byte {
|
||||
return bytes.Join(pBytes, []byte(""))
|
||||
}
|
||||
|
||||
func BytesCombine(pBytes ...[]byte) []byte {
|
||||
length := len(pBytes)
|
||||
s := make([][]byte, length)
|
||||
for index := 0; index < length; index++ {
|
||||
s[index] = pBytes[index]
|
||||
}
|
||||
sep := []byte("")
|
||||
return bytes.Join(s, sep)
|
||||
}
|
||||
|
||||
func ParseIPAddr(ip string) string {
|
||||
ipAddr := net.ParseIP(ip)
|
||||
|
||||
if ipAddr != nil {
|
||||
if ipAddr.To4() != nil {
|
||||
return IsIPv4
|
||||
} else {
|
||||
return IsIPv6
|
||||
}
|
||||
}
|
||||
|
||||
return NonIP
|
||||
}
|
||||
|
||||
func CombineHostUri(ip string, port string) string {
|
||||
var hostUri string = ""
|
||||
ipType := ParseIPAddr(ip)
|
||||
if ipType == IsIPv4 {
|
||||
hostUri = fmt.Sprintf("http://%s:%v", ip, port)
|
||||
} else {
|
||||
hostUri = fmt.Sprintf("http://[%s]:%v", ip, port)
|
||||
}
|
||||
|
||||
return hostUri
|
||||
}
|
||||
|
||||
func StructToMap(obj interface{}) map[string]interface{} {
|
||||
objValue := reflect.ValueOf(obj)
|
||||
objType := objValue.Type()
|
||||
|
||||
m := make(map[string]interface{})
|
||||
|
||||
for i := 0; i < objValue.NumField(); i++ {
|
||||
field := objValue.Field(i)
|
||||
fieldName := objType.Field(i).Name
|
||||
|
||||
m[fieldName] = field.Interface()
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// ToMap 结构体转为Map[string]interface{}
|
||||
func ToMap(in interface{}, tagName string) (map[string]interface{}, error) {
|
||||
out := make(map[string]interface{})
|
||||
|
||||
v := reflect.ValueOf(in)
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
if v.Kind() != reflect.Struct { // 非结构体返回错误提示
|
||||
return nil, fmt.Errorf("ToMap only accepts struct or struct pointer; got %T", v)
|
||||
}
|
||||
|
||||
t := v.Type()
|
||||
// 遍历结构体字段
|
||||
// 指定tagName值为map中key;字段值为map中value
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
fi := t.Field(i)
|
||||
if tagValue := fi.Tag.Get(tagName); tagValue != "" {
|
||||
out[tagValue] = v.Field(i).Interface()
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func ZipOneFile(srcFile, dstZip string, pathFlag bool) error {
|
||||
zipFile, err := os.Create(dstZip)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer zipFile.Close()
|
||||
|
||||
zipWriter := zip.NewWriter(zipFile)
|
||||
defer zipWriter.Close()
|
||||
|
||||
fileToCompress, err := os.Open(srcFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer fileToCompress.Close()
|
||||
|
||||
var fileInZip io.Writer
|
||||
if pathFlag {
|
||||
fileInZip, err = zipWriter.Create(srcFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// 获取文件的基本名称
|
||||
fileName := filepath.Base(fileToCompress.Name())
|
||||
fileInZip, err = zipWriter.Create(fileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
_, err = io.Copy(fileInZip, fileToCompress)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ZipDirectoryFile(srcDir, dstZip string) error {
|
||||
// Create a new zip file
|
||||
zipfileWriter, err := os.Create(dstZip)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer zipfileWriter.Close()
|
||||
|
||||
// Create a new zip archive
|
||||
zipWriter := zip.NewWriter(zipfileWriter)
|
||||
defer zipWriter.Close()
|
||||
|
||||
// Walk through the directory and add files to the zip archive
|
||||
err = filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create a new file header for the current file
|
||||
header, err := zip.FileInfoHeader(info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set the name of the file within the zip archive
|
||||
header.Name = filepath.Join(filepath.Base(srcDir), path[len(srcDir):])
|
||||
|
||||
// If the current file is a directory, skip it
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create a new file in the zip archive
|
||||
fileWriter, err := zipWriter.CreateHeader(header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Open the current file
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// Copy the contents of the current file to the zip archive
|
||||
_, err = io.Copy(fileWriter, file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// 判断软件包是rpm或者deb, 1:rpm, 2:deb, 0:unknown format
|
||||
func JudgeRpmOrDebPackage(filePath string) (int, error) {
|
||||
var fileType int = 0
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return fileType, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// Read the first 6 bytes of the file
|
||||
header := make([]byte, 6)
|
||||
_, err = file.Read(header)
|
||||
if err != nil {
|
||||
return fileType, err
|
||||
}
|
||||
|
||||
// Check the magic numbers to determine the package format
|
||||
if string(header) == "!<arch>" {
|
||||
fileType = 1
|
||||
} else if string(header) == "!<arch\n" || string(header) == "!<arch\r" {
|
||||
fileType = 2
|
||||
} else {
|
||||
fileType = 0
|
||||
}
|
||||
|
||||
return fileType, nil
|
||||
}
|
||||
|
||||
func isRpmPackage(file *os.File) bool {
|
||||
// RPM packages start with the magic number "EDABEEDB"
|
||||
magic := []byte{0xED, 0xAB, 0xEE, 0xDB}
|
||||
buffer := make([]byte, len(magic))
|
||||
|
||||
_, err := file.Read(buffer)
|
||||
if err != nil && err != io.EOF {
|
||||
return false
|
||||
}
|
||||
|
||||
return string(buffer) == string(magic)
|
||||
}
|
||||
|
||||
func isDebPackage(file *os.File) bool {
|
||||
// DEB packages start with the magic number "!<arch>\n"
|
||||
magic := []byte("!<arch>\n")
|
||||
buffer := make([]byte, len(magic))
|
||||
|
||||
_, err := file.Read(buffer)
|
||||
if err != nil && err != io.EOF {
|
||||
return false
|
||||
}
|
||||
|
||||
return string(buffer) == string(magic)
|
||||
}
|
||||
|
||||
func CheckRpmOrDebPackage(filePath string) (int, error) {
|
||||
var fileType int = 0
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return fileType, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
isRpm := isRpmPackage(file)
|
||||
isDeb := isDebPackage(file)
|
||||
|
||||
if isRpm {
|
||||
fileType = 1
|
||||
} else if isDeb {
|
||||
fileType = 2
|
||||
} else {
|
||||
fileType = 0
|
||||
}
|
||||
|
||||
return fileType, nil
|
||||
}
|
||||
|
||||
func IsRpmOrDebPackage(filePath string) int {
|
||||
var fileType int = 0
|
||||
|
||||
if strings.Contains(filePath, ".rpm") {
|
||||
fileType = 1
|
||||
} else if strings.Contains(filePath, ".deb") {
|
||||
fileType = 2
|
||||
} else {
|
||||
fileType = 0
|
||||
}
|
||||
|
||||
return fileType
|
||||
}
|
||||
Reference in New Issue
Block a user