~tim/mailchimp3

ref: 4a85279d09c7b51b252b75352aa32d0df5ea8a56 mailchimp3/lib/mailchimp3/endpoint.rb -rw-r--r-- 3.0 KiB
4a85279dTim Morgan Remove respond_to? 6 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
require 'faraday'
require 'faraday_middleware'

module MailChimp3
  class Endpoint
    attr_reader :url, :last_result

    def initialize(oauth_access_token: nil, basic_auth_key: nil, dc: nil, url: nil)
      @oauth_access_token = oauth_access_token
      @basic_auth_key = basic_auth_key
      @dc = dc
      @dc ||= @basic_auth_key.split('-').last if @basic_auth_key
      @url = url || _build_url
      fail Errors::DataCenterRequiredError, 'You must pass dc.' unless @dc || @url
      @cache = {}
    end

    def method_missing(method_name, *_args)
      _build_endpoint(method_name.to_s)
    end

    def [](id)
      _build_endpoint(id.to_s)
    end

    def get(params = {})
      @last_result = _connection.get(@url, params)
      _build_response(@last_result)
    end

    def post(body = {})
      @last_result = _connection.post(@url) do |req|
        req.body = _build_body(body)
      end
      _build_response(@last_result)
    end

    def patch(body = {})
      @last_result = _connection.patch(@url) do |req|
        req.body = _build_body(body)
      end
      _build_response(@last_result)
    end

    def delete
      @last_result = _connection.delete(@url)
      if @last_result.status == 204
        true
      else
        _build_response(@last_result)
      end
    end

    private

    def _build_response(result)
      case result.status
      when 200..299
        result.body
      when 400
        fail Errors::BadRequest, result
      when 401
        fail Errors::Unauthorized, result
      when 403
        fail Errors::Forbidden, result
      when 404
        fail Errors::NotFound, result
      when 405
        fail Errors::MethodNotAllowed, result
      when 422
        fail Errors::UnprocessableEntity, result
      when 400..499
        fail Errors::ClientError, result
      when 500
        fail Errors::InternalServerError, result
      when 500..599
        fail Errors::ServerError, result
      else
        fail "unknown status #{result.status}"
      end
    end

    def _build_body(body)
      if _needs_url_encoded?
        Faraday::Utils.build_nested_query(body)
      else
        body.to_json
      end
    end

    def _needs_url_encoded?
      @url =~ /oauth\/[a-z]+\z/
    end

    def _build_endpoint(path)
      @cache[path] ||= begin
        self.class.new(
          url: File.join(url, path.to_s),
          basic_auth_key: @basic_auth_key,
          oauth_access_token: @oauth_access_token
        )
      end
    end

    def _build_url
      "https://#{@dc}.api.mailchimp.com/3.0"
    end

    def _connection
      @connection ||= Faraday.new(url: url) do |faraday|
        faraday.adapter :excon
        faraday.response :json, content_type: /\bjson$/
        if @basic_auth_key
          faraday.basic_auth '', @basic_auth_key
        elsif @oauth_access_token
          faraday.headers['Authorization'] = "Bearer #{@oauth_access_token}"
        else
          fail Errors::AuthRequiredError, "You must specify either HTTP basic auth credentials or an OAuth2 access token."
        end
      end
    end
  end
end