~tim/mailchimp3

mailchimp3/lib/mailchimp3/endpoint.rb -rw-r--r-- 3.5 KiB
836bcd45Tim Morgan Release 1.3.1 3 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
124
125
126
127
128
129
130
131
132
133
require 'faraday'
require 'json'

module MailChimp3
  class Endpoint
    attr_reader :url, :last_result

    def initialize(oauth_access_token: nil, basic_auth_key: nil, dc: nil, url: nil, version: 3)
      @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
      @version = version
      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|
        body[:apikey] = @oauth_access_token || @basic_auth_key if @version == 2
        req.body = body.to_json
      end
      _build_response(@last_result)
    end

    def patch(body = {})
      @last_result = _connection.patch(@url) do |req|
        req.body = body.to_json
      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

    def v2
      self.class.new(
        url: _build_v2_url,
        basic_auth_key: @basic_auth_key,
        oauth_access_token: @oauth_access_token,
        version: 2
      )
    end

    private

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

    def _parse_body(result)
      JSON.parse(result.body)
    rescue JSON::ParserError
      raise Errors::ServerError, status: result.status, body: result.body
    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,
          version: @version
        )
      end
    end

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

    def _build_v2_url
      "https://#{@dc}.api.mailchimp.com/2.0/"
    end

    def _connection
      @connection ||= Faraday.new(url: url) do |faraday|
        faraday.adapter :excon
        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