github.com/go-email-validator/go-email-validator@v0.0.0-20230409163946-b8b9e6a0552e/pkg/ev/validator_gravatar.go (about) 1 package ev 2 3 import ( 4 "crypto/md5" //nolint:gosec 5 "fmt" 6 "github.com/go-email-validator/go-email-validator/pkg/ev/utils" 7 "net/http" 8 "time" 9 ) 10 11 const ( 12 // GravatarValidatorName is name for validation by https://www.gravatar.com/ 13 GravatarValidatorName ValidatorName = "Gravatar" 14 // GravatarURL is url for gravatar validation 15 GravatarURL string = "https://www.gravatar.com/avatar/%x?d=404" 16 // DefaultGravatarTimeout is default timeout for gravatar connection 17 DefaultGravatarTimeout = 5 * time.Second 18 ) 19 20 // GravatarErr is text for GravatarError.Error 21 const GravatarErr = "GravatarError" 22 23 // GravatarValidationResult is result of GravatarValidatorName 24 type GravatarValidationResult interface { 25 URL() string 26 ValidationResult 27 } 28 29 // NewGravatarValidationResult instantiates result of GravatarValidationResult 30 func NewGravatarValidationResult(url string, result *AValidationResult) GravatarValidationResult { 31 return gravatarValidationResult{url: url, AValidationResult: result} 32 } 33 34 // GetMD5Hash is function interface, which returns md5 for string 35 type GetMD5Hash func(str string) []byte 36 37 // DefaultGetMD5Hash is a default implementation of GetMD5Hash 38 func DefaultGetMD5Hash(str string) []byte { 39 h := md5.New() 40 h.Write([]byte(str)) 41 return h.Sum(nil) 42 } 43 44 // GravatarError is GravatarValidatorName error 45 type GravatarError struct{} 46 47 func (GravatarError) Error() string { 48 return GravatarErr 49 } 50 51 // NewGravatarValidator instantiates GravatarValidatorName validator with GravatarURL for validation 52 func NewGravatarValidator() Validator { 53 return NewGravatarValidatorWithURL(GravatarURL) 54 } 55 56 // NewGravatarValidatorWithURL instantiates GravatarValidatorName validator 57 func NewGravatarValidatorWithURL(gravatarURL string) Validator { 58 return gravatarValidator{ 59 h: DefaultGetMD5Hash, 60 url: gravatarURL, 61 } 62 } 63 64 type gravatarValidator struct { 65 AValidatorWithoutDeps 66 h GetMD5Hash 67 url string 68 } 69 70 func (g gravatarValidator) GetDeps() []ValidatorName { 71 return []ValidatorName{SyntaxValidatorName} 72 } 73 74 func (g gravatarValidator) Validate(input Input, results ...ValidationResult) ValidationResult { 75 syntaxResult := results[0].(SyntaxValidatorResult) 76 if !syntaxResult.IsValid() { 77 return gravatarGetError(NewDepsError()) 78 } 79 80 var opts = DefaultGravatarOptions() 81 if optsInterface := input.Option(GravatarValidatorName); optsInterface != nil { 82 opts = optsInterface.(GravatarOptions) 83 } 84 85 client := &http.Client{Timeout: opts.Timeout()} 86 87 gravatarURL := fmt.Sprintf( 88 GravatarURL, 89 g.h(input.Email().String()), 90 ) 91 resp, err := client.Head(gravatarURL) 92 if err != nil { 93 return gravatarGetError(err) 94 } 95 defer resp.Body.Close() 96 if resp.StatusCode != 200 { 97 return gravatarGetError(GravatarError{}) 98 } 99 100 return NewGravatarValidationResult( 101 gravatarURL, 102 NewValidResult(GravatarValidatorName).(*AValidationResult), 103 ) 104 } 105 106 func gravatarGetError(err error) ValidationResult { 107 return NewGravatarValidationResult( 108 "", 109 NewResult(false, utils.Errs(err), nil, GravatarValidatorName).(*AValidationResult), 110 ) 111 } 112 113 type gravatarValidationResult struct { 114 *AValidationResult 115 url string 116 } 117 118 func (v gravatarValidationResult) URL() string { 119 return v.url 120 } 121 122 // GravatarOptions describes gravatar options 123 type GravatarOptions interface { 124 Timeout() time.Duration 125 } 126 127 // GravatarOptionsDTO is dto for NewGravatarOptions 128 type GravatarOptionsDTO struct { 129 Timeout time.Duration 130 } 131 132 var defaultOptions = NewGravatarOptions(GravatarOptionsDTO{ 133 Timeout: DefaultGravatarTimeout, 134 }) 135 136 // DefaultGravatarOptions returns options with default values 137 func DefaultGravatarOptions() GravatarOptions { 138 return defaultOptions 139 } 140 141 // NewGravatarOptions instantiates GravatarOptions 142 func NewGravatarOptions(dto GravatarOptionsDTO) GravatarOptions { 143 return &gravatarOptions{ 144 timeout: dto.Timeout, 145 } 146 } 147 148 type gravatarOptions struct { 149 timeout time.Duration 150 } 151 152 func (i *gravatarOptions) Timeout() time.Duration { 153 return i.timeout 154 }