package common import ( "encoding/base64" "encoding/json" "fmt" kitutil "github.com/QuantumNous/new-api/relaykit/relayconvert/kitutil" "strconv" "strings" "unsafe" "github.com/samber/lo" ) const LocalLogContentLimit = 2048 // LocalLogPreview limits log-only content unless debug logging is enabled. func LocalLogPreview(content string) string { if DebugEnabled || len(content) <= LocalLogContentLimit { return content } return fmt.Sprintf("%s... [truncated, original_length=%d, limit=%d]", content[:LocalLogContentLimit], len(content), LocalLogContentLimit) } func GetStringIfEmpty(str string, defaultValue string) string { if str == "" { return defaultValue } return str } func GetRandomString(length int) string { if length <= 0 { return "" } return lo.RandomString(length, lo.AlphanumericCharset) } func MapToJsonStr(m map[string]interface{}) string { bytes, err := json.Marshal(m) if err != nil { return "" } return string(bytes) } func StrToMap(str string) (map[string]interface{}, error) { m := make(map[string]interface{}) err := Unmarshal([]byte(str), &m) if err != nil { return nil, err } return m, nil } func StrToJsonArray(str string) ([]interface{}, error) { var js []interface{} err := json.Unmarshal([]byte(str), &js) if err != nil { return nil, err } return js, nil } func IsJsonArray(str string) bool { var js []interface{} return json.Unmarshal([]byte(str), &js) == nil } func IsJsonObject(str string) bool { var js map[string]interface{} return json.Unmarshal([]byte(str), &js) == nil } func String2Int(str string) int { num, err := strconv.Atoi(str) if err != nil { return 0 } return num } func StringsContains(strs []string, str string) bool { for _, s := range strs { if s == str { return true } } return false } // StringToByteSlice []byte only read, panic on append func StringToByteSlice(s string) []byte { tmp1 := (*[2]uintptr)(unsafe.Pointer(&s)) tmp2 := [3]uintptr{tmp1[0], tmp1[1], tmp1[1]} return *(*[]byte)(unsafe.Pointer(&tmp2)) } func EncodeBase64(str string) string { return base64.StdEncoding.EncodeToString([]byte(str)) } func GetJsonString(data any) string { if data == nil { return "" } b, _ := json.Marshal(data) return string(b) } // NormalizeBillingPreference clamps the billing preference to valid values. func NormalizeBillingPreference(pref string) string { switch strings.TrimSpace(pref) { case "subscription_first", "wallet_first", "subscription_only", "wallet_only": return strings.TrimSpace(pref) default: return "subscription_first" } } // MaskEmail masks a user email to prevent PII leakage in logs // Returns "***masked***" if email is empty, otherwise shows only the domain part func MaskEmail(email string) string { if email == "" { return "***masked***" } // Find the @ symbol atIndex := strings.Index(email, "@") if atIndex == -1 { // No @ symbol found, return masked return "***masked***" } // Return only the domain part with @ symbol return "***@" + email[atIndex+1:] } // MaskSensitiveInfo moved to the conversion kit (kitutil) because the types // package error formatting depends on it; host callers keep this name. func MaskSensitiveInfo(str string) string { return kitutil.MaskSensitiveInfo(str) }