You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
openim-sdk-cpp/go/chao-sdk-core/pkg/utils/utils.go

555 lines
12 KiB

// Copyright © 2023 OpenIM SDK. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package utils
import (
"crypto/md5"
"encoding/hex"
"encoding/json"
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
"github.com/openimsdk/openim-sdk-core/v3/sdk_struct"
"sort"
"github.com/golang/protobuf/jsonpb"
"github.com/golang/protobuf/proto"
"reflect"
"github.com/pkg/errors"
"math/rand"
"runtime"
"strconv"
"strings"
"time"
)
func OperationIDGenerator() string {
return strconv.FormatInt(time.Now().UnixNano()+int64(rand.Uint32()), 10)
}
func GetMsgID(sendID string) string {
t := Int64ToString(GetCurrentTimestampByNano())
return Md5(t + sendID + Int64ToString(rand.Int63n(GetCurrentTimestampByNano())))
}
func Md5(s string) string {
h := md5.New()
h.Write([]byte(s))
cipher := h.Sum(nil)
return hex.EncodeToString(cipher)
}
//Get the current timestamp by Second
func GetCurrentTimestampBySecond() int64 {
return time.Now().Unix()
}
// Get the current timestamp by Mill
func GetCurrentTimestampByMill() int64 {
return time.Now().UnixNano() / 1e6
}
// Convert nano timestamp to time.Time type
func UnixNanoSecondToTime(nanoSecond int64) time.Time {
return time.Unix(0, nanoSecond)
}
// Get the current timestamp by Nano
func GetCurrentTimestampByNano() int64 {
return time.Now().UnixNano()
}
func StructToJsonString(param interface{}) string {
dataType, err := json.Marshal(param)
if err != nil {
panic(err)
}
dataString := string(dataType)
return dataString
}
func StructToJsonStringDefault(param interface{}) string {
if reflect.TypeOf(param).Kind() == reflect.Slice && reflect.ValueOf(param).Len() == 0 {
return "[]"
}
return StructToJsonString(param)
}
// The incoming parameter must be a pointer
func JsonStringToStruct(s string, args interface{}) error {
return Wrap(json.Unmarshal([]byte(s), args), "json Unmarshal failed")
}
func FirstLower(s string) string {
if s == "" {
return ""
}
return strings.ToLower(s[:1]) + s[1:]
}
//Convert timestamp to time.Time type
func UnixSecondToTime(second int64) time.Time {
return time.Unix(second, 0)
}
func IntToString(i int) string {
return strconv.FormatInt(int64(i), 10)
}
func Int32ToString(i int32) string {
return strconv.FormatInt(int64(i), 10)
}
func Int64ToString(i int64) string {
return strconv.FormatInt(i, 10)
}
func StringToInt64(i string) int64 {
j, _ := strconv.ParseInt(i, 10, 64)
return j
}
func StringToInt(i string) int {
j, _ := strconv.Atoi(i)
return j
}
func RunFuncName() string {
pc, _, _, _ := runtime.Caller(2)
return CleanUpfuncName(runtime.FuncForPC(pc).Name())
}
func LogBegin(v ...interface{}) {
//if constant.SdkLogFlag == 1 {
// return
//}
//if open_im_sdk.logger != nil {
// log2.NewInfo("", v...)
// return
//}
//pc, b, c, _ := runtime.Caller(1)
//fname := runtime.FuncForPC(pc).Name()
//i := strings.LastIndex(b, "/")
//if i != -1 {
// sLog.Println(" [", b[i+1:len(b)], ":", c, "]", cleanUpfuncName(fname), "call funcation begin, args: ", v)
//}
}
func LogEnd(v ...interface{}) {
//if constant.SdkLogFlag == 1 {
// return
//}
//if open_im_sdk.logger != nil {
// log2.NewInfo("", v...)
// return
//}
//pc, b, c, _ := runtime.Caller(1)
//fname := runtime.FuncForPC(pc).Name()
//i := strings.LastIndex(b, "/")
//if i != -1 {
// sLog.Println(" [", b[i+1:len(b)], ":", c, "]", cleanUpfuncName(fname), "call funcation end, args: ", v)
//}
}
func LogStart(v ...interface{}) {
//if constant.SdkLogFlag == 1 {
// return
//}
//if open_im_sdk.logger != nil {
// log2.NewInfo("", v...)
// return
//}
//pc, b, c, _ := runtime.Caller(1)
//fname := runtime.FuncForPC(pc).Name()
//i := strings.LastIndex(b, "/")
//if i != -1 {
// sLog.Println(" [", b[i+1:len(b)], ":", c, "]", cleanUpfuncName(fname), "funcation start, args: ", v)
//}
}
func LogFReturn(v ...interface{}) {
//if constant.SdkLogFlag == 1 {
// return
//}
//if open_im_sdk.logger != nil {
// log2.NewInfo("", v...)
// return
//}
//pc, b, c, _ := runtime.Caller(1)
//fname := runtime.FuncForPC(pc).Name()
//i := strings.LastIndex(b, "/")
//if i != -1 {
// sLog.Println("[", b[i+1:len(b)], ":", c, "]", cleanUpfuncName(fname), "failed return args(info): ", v)
//}
}
func LogSReturn(v ...interface{}) {
//if constant.SdkLogFlag == 1 {
// return
//}
//if open_im_sdk.logger != nil {
// log2.NewInfo("", v...)
// return
//}
//pc, b, c, _ := runtime.Caller(1)
//fname := runtime.FuncForPC(pc).Name()
//i := strings.LastIndex(b, "/")
//if i != -1 {
// sLog.Println("[", b[i+1:len(b)], ":", c, "]", cleanUpfuncName(fname), "success return args(info): ", v)
//}
}
func sdkLog(v ...interface{}) {
//if constant.SdkLogFlag == 1 {
// return
//}
//if open_im_sdk.logger != nil {
// log2.NewInfo("", v...)
// return
//}
//_, b, c, _ := runtime.Caller(1)
//i := strings.LastIndex(b, "/")
//if i != -1 {
// sLog.Println("[", b[i+1:len(b)], ":", c, "]", v)
//}
}
type LogInfo struct {
Info string `json:"info"`
}
// judge a string whether in the string list
func IsContain(target string, List []string) bool {
for _, element := range List {
if target == element {
return true
}
}
return false
}
func IsContainInt(target int, List []int) bool {
for _, element := range List {
if target == element {
return true
}
}
return false
}
func IsContainUInt32(target uint32, List []uint32) bool {
for _, element := range List {
if target == element {
return true
}
}
return false
}
func GetSwitchFromOptions(Options map[string]bool, key string) (result bool) {
if flag, ok := Options[key]; !ok || flag {
return true
}
return false
}
func SetSwitchFromOptions(Options map[string]bool, key string, value bool) {
Options[key] = value
}
func Wrap(err error, message string) error {
return errors.Wrap(err, "==> "+printCallerNameAndLine()+message)
}
func Unwrap(err error) error {
for err != nil {
unwrap, ok := err.(interface {
Unwrap() error
})
if !ok {
break
}
err = unwrap.Unwrap()
}
return err
}
func WithMessage(err error, message string) error {
return errors.WithMessage(err, "==> "+printCallerNameAndLine()+message)
}
func GetSelfFuncName() string {
pc, _, _, _ := runtime.Caller(1)
return CleanUpfuncName(runtime.FuncForPC(pc).Name())
}
func CleanUpfuncName(funcName string) string {
end := strings.LastIndex(funcName, ".")
if end == -1 {
return ""
}
return funcName[end+1:]
}
func printCallerNameAndLine() string {
pc, _, line, _ := runtime.Caller(2)
return runtime.FuncForPC(pc).Name() + "()@" + strconv.Itoa(line) + ": "
}
func StructToMap(user interface{}) map[string]interface{} {
data, _ := json.Marshal(user)
m := make(map[string]interface{})
json.Unmarshal(data, &m)
return m
}
// funcation GetConversationIDBySessionType(sourceID string, sessionType int) string {
// switch sessionType {
// case constant.SingleChatType:
// return "single_" + sourceID
// case constant.GroupChatType:
// return "group_" + sourceID
// case constant.SuperGroupChatType:
// return "super_group_" + sourceID
// case constant.NotificationChatType:
// return "notification_" + sourceID
// }
// return ""
// }
func GetConversationIDByMsg(msg *sdk_struct.MsgStruct) string {
switch msg.SessionType {
case constant.SingleChatType:
l := []string{msg.SendID, msg.RecvID}
sort.Strings(l)
return "si_" + strings.Join(l, "_") // single chat
case constant.GroupChatType:
return "g_" + msg.GroupID // group chat
case constant.SuperGroupChatType:
return "sg_" + msg.GroupID // super group chat
case constant.NotificationChatType:
return "sn_" + msg.SendID + "_" + msg.RecvID // server notification chat
}
return ""
}
func GetConversationIDByGroupID(groupID string) string {
return "sg_" + groupID
}
func GetConversationTableName(conversationID string) string {
return constant.ChatLogsTableNamePre + conversationID
}
func GetTableName(conversationID string) string {
return constant.ChatLogsTableNamePre + conversationID
}
func GetErrTableName(conversationID string) string {
return constant.SuperGroupErrChatLogsTableNamePre + conversationID
}
type Comparable interface {
~int | ~string | ~float64 | ~int32
}
func RemoveRepeatedElementsInList[T Comparable](slc []T) []T {
var result []T
tempMap := map[T]struct{}{}
for _, e := range slc {
if _, found := tempMap[e]; !found {
tempMap[e] = struct{}{}
result = append(result, e)
}
}
return result
}
func RemoveOneInList[T comparable](slice []T, val T) []T {
for i, v := range slice {
if v == val {
return append(slice[:i], slice[i+1:]...)
}
}
return slice
}
/*
*
KMP
*
*/
func KMP(rMainString string, rSubString string) (isInMainString bool) {
mainString := strings.ToLower(rMainString)
subString := strings.ToLower(rSubString)
mainIdx := 0
subIdx := 0
mainLen := len(mainString)
subLen := len(subString)
next := computeNextArray(subString)
for {
if mainIdx >= mainLen || subIdx >= subLen {
break
}
if mainString[mainIdx] == subString[subIdx] {
mainIdx++
subIdx++
} else {
if subIdx != 0 {
subIdx = next[subIdx-1]
} else {
mainIdx++
}
}
}
if subIdx >= subLen {
if mainIdx-subLen >= 0 {
return true
}
}
return false
}
func computeNextArray(subString string) []int {
next := make([]int, len(subString))
index := 0
i := 1
for i < len(subString) {
if subString[i] == subString[index] {
next[i] = index + 1
i++
index++
} else {
if index != 0 {
index = next[index-1]
} else {
i++
}
}
}
return next
}
func TrimStringList(list []string) (result []string) {
for _, v := range list {
if len(strings.Trim(v, " ")) != 0 {
result = append(result, v)
}
}
return result
}
// Get the intersection of two slices
func Intersect(slice1, slice2 []int64) []int64 {
m := make(map[int64]bool)
n := make([]int64, 0)
for _, v := range slice1 {
m[v] = true
}
for _, v := range slice2 {
flag, _ := m[v]
if flag {
n = append(n, v)
}
}
return n
}
// Get the diff of two slices
func DifferenceSubset(mainSlice, subSlice []int64) []int64 {
m := make(map[int64]bool)
n := make([]int64, 0)
for _, v := range subSlice {
m[v] = true
}
for _, v := range mainSlice {
if !m[v] {
n = append(n, v)
}
}
return n
}
func DifferenceSubsetString(mainSlice, subSlice []string) []string {
m := make(map[string]bool)
n := make([]string, 0)
for _, v := range subSlice {
m[v] = true
}
for _, v := range mainSlice {
if !m[v] {
n = append(n, v)
}
}
return n
}
func JsonDataOne(pb proto.Message) map[string]interface{} {
return ProtoToMap(pb, false)
}
func ProtoToMap(pb proto.Message, idFix bool) map[string]interface{} {
marshaler := jsonpb.Marshaler{
OrigName: true,
EnumsAsInts: false,
EmitDefaults: true,
}
s, _ := marshaler.MarshalToString(pb)
out := make(map[string]interface{})
json.Unmarshal([]byte(s), &out)
if idFix {
if _, ok := out["id"]; ok {
out["_id"] = out["id"]
delete(out, "id")
}
}
return out
}
func GetUserIDForMinSeq(userID string) string {
return "u_" + userID
}
func GetGroupIDForMinSeq(groupID string) string {
return "g_" + groupID
}
func TimeStringToTime(timeString string) (time.Time, error) {
t, err := time.Parse("2006-01-02", timeString)
return t, err
}
func TimeToString(t time.Time) string {
return t.Format("2006-01-02")
}
func Uint32ListConvert(list []uint32) []int64 {
var result []int64
for _, v := range list {
result = append(result, int64(v))
}
return result
}
func UnmarshalNotificationElem(bytes []byte, t interface{}) error {
var n sdk_struct.NotificationElem
err := JsonStringToStruct(string(bytes), &n)
if err != nil {
return err
}
err = JsonStringToStruct(n.Detail, t)
if err != nil {
return err
}
return nil
}