123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- package api
- import (
- "net/url"
- "time"
- "log"
- "os"
- )
- const (
- DefaultContentType = "application/json"
- DefaultAccept = DefaultContentType
- DefaultCacheControl = "no-cache"
- MaxEntitiesPerRequest = 250
- )
- type ClientOptions struct {
- URL string `json:"url"`
- RedirectURL string `json:"redirect_url"`
- AuthCode string `json:"auth_code"`
- ClientId string `json:"client_id"`
- ClientSecret string `json:"client_secret"`
- AccessToken string `json:"access_token"`
- ExpirationAt time.Time `json:"expiration_at,omitempty"`
- RefreshToken string `json:"refresh_token"`
- }
- type Client struct {
- *log.Logger
- options ClientOptions
- BaseURL *url.URL
- secretStoreFilePath string
- Debug bool
- availableRequests int
- mrps int
- ticker *time.Ticker
- req, reqNeed chan struct{}
- requestsMade int64
- }
- type OAuthTokenResponse struct {
- TokenType string `json:"token_type"`
- ExpiresIn int `json:"expires_in"`
- AccessToken string `json:"access_token"`
- RefreshToken string `json:"refresh_token"`
- }
- type TokenPair struct {
- Access, Refresh string
- }
- func NewAPI(secretPath string) (*Client, error) {
- client := &Client{
- Logger: log.New(
- os.Stdout,
- "AmoCRM client: ",
- log.Ldate | log.Ltime,
- ),
- secretStoreFilePath: secretPath,
- }
- options, err := client.readSecret()
- if err != nil {
- return nil, NewErrorAPI(err)
- }
- if client.Debug {
- client.Printf("ClientOptions: %v\n", options)
- }
- if options.URL == "" || options.RedirectURL == "" {
- return nil, NewErrorAPI(ErrInvalidOptionsURL)
- }
- parsedURL, err := url.Parse(options.URL)
- if err != nil {
- return nil, NewErrorAPI(err)
- }
- client.BaseURL = parsedURL
- client.options = options
- var (
- //pair *TokenPair
- exchangeErr error
- exchanged bool
- )
- if client.options.AccessToken == "" &&
- client.options.RefreshToken == "" {
- if client.options.ClientSecret == "" ||
- client.options.ClientId == "" ||
- client.options.AuthCode == "" {
- return nil, NewErrorAPI(
- ErrInvalidExchangeAuthOptions,
- )
- }
- _, exchangeErr = client.ExchangeAuth()
- exchanged = true
- }
- if (!exchanged || exchangeErr != nil) &&
- options.RefreshToken != "" {
- // Refreshing token before the work.
- // Should think of how often should refresh
- // the token. (see the ExpiresIn)
- _, err = client.RefreshToken()
- if err != nil {
- return nil, NewErrorAPI(err)
- }
- }
- return client, nil
- }
- // Set maximum requests per second.
- func (client *Client) SetMRPS(rps int) *Client {
- client.mrps = rps
- client.req = make(chan struct{})
- client.reqNeed = make(chan struct{})
- client.ticker = time.NewTicker(
- time.Second/time.Duration(rps),
- )
- go func() {
- for {
- select {
- case <- client.reqNeed :
- client.req <- struct{}{}
- }
- <-client.ticker.C
- }
- }()
- return client
- }
- func (client *Client) waitInQueue() bool {
- // Just leaving if MRPS is not set.
- if client.mrps == 0 {
- return false
- }
- client.reqNeed <- struct{}{}
- <- client.req
- return true
- }
- func (client *Client) finishRequest() {
- }
- func (client *Client) RequestsMade() int64 {
- return client.requestsMade
- }
|