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  }