Enhance MySubaru API integration with improved error handling and new utility functions
All checks were successful
Golan Testing / testing (1.24.x, ubuntu-latest) (push) Successful in 25s
All checks were successful
Golan Testing / testing (1.24.x, ubuntu-latest) (push) Successful in 25s
- Refactor Response struct's parse method to return detailed error messages based on API error codes. - Introduce UnixTime type for handling Unix timestamps in JSON marshaling and unmarshaling. - Add email masking utility function to obfuscate email addresses for privacy. - Implement containsValueInStruct function to check for substring presence in struct fields. - Create comprehensive unit tests for UnixTime, email masking, and struct value checking. - Update vehicle service request method documentation for clarity.
This commit is contained in:
62
utils.go
62
utils.go
@ -1,7 +1,10 @@
|
||||
package mysubaru
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"net/mail"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -114,6 +117,65 @@ func transcodeDigits(vin string) int {
|
||||
return digitSum
|
||||
}
|
||||
|
||||
// emailMasking takes an email address as input and returns a version of the email
|
||||
// with the username part partially hidden for privacy. Only the first and last
|
||||
// characters of the username are visible, with the middle characters replaced by asterisks.
|
||||
// The function validates the email format before processing.
|
||||
// Returns the obfuscated email or an error if the input is not a valid email address.
|
||||
func emailMasking(email string) (string, error) {
|
||||
_, err := mail.ParseAddress(email)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("invalid email address: %s", email)
|
||||
}
|
||||
|
||||
re1 := regexp.MustCompile(`^(.*?)@(.*)$`)
|
||||
matches := re1.FindStringSubmatch(email)
|
||||
|
||||
var username, domain string
|
||||
if len(matches) == 3 { // Expecting the full match, username, and domain
|
||||
username = matches[1]
|
||||
domain = matches[2]
|
||||
} else {
|
||||
return "", fmt.Errorf("invalid email format: %s", email)
|
||||
}
|
||||
|
||||
re2 := regexp.MustCompile(`(.)(.*)(.)`)
|
||||
|
||||
replacedString := re2.ReplaceAllStringFunc(username, func(s string) string {
|
||||
firstChar := string(s[0])
|
||||
lastChar := string(s[len(s)-1])
|
||||
middleCharsCount := len(s) - 2
|
||||
|
||||
if middleCharsCount < 0 { // Should not happen with the length check above, but for robustness
|
||||
return s
|
||||
}
|
||||
return firstChar + strings.Repeat("*", middleCharsCount) + lastChar
|
||||
})
|
||||
|
||||
return replacedString + "@" + domain, nil
|
||||
}
|
||||
|
||||
// containsValueInStruct checks if any string field in the given struct 's' contains the specified 'search' substring (case-insensitive).
|
||||
// It returns true if at least one string field contains the substring, and false otherwise.
|
||||
// If 's' is not a struct, it returns false.
|
||||
func containsValueInStruct(s any, search string) bool {
|
||||
val := reflect.ValueOf(s)
|
||||
if val.Kind() != reflect.Struct {
|
||||
return false // Not a struct
|
||||
}
|
||||
|
||||
for i := 0; i < val.NumField(); i++ {
|
||||
field := val.Field(i)
|
||||
if field.Kind() == reflect.String {
|
||||
if strings.Contains(strings.ToLower(field.String()), strings.ToLower(search)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// timeTrack .
|
||||
// func timeTrack(name string) {
|
||||
// start := time.Now()
|
||||
|
Reference in New Issue
Block a user