~tim/mailchimp3

ref: b32428ccd5d2fc119fb236fd101b78bce1ac88df mailchimp3/lib/mailchimp3/endpoint.rb -rw-r--r-- 3.2 KiB
b32428ccTim Morgan Add support for OAuth2 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
124
125
126
127
128
129
130
131
132
133
134
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 respond_to?(method_name)
      endpoint = _build_endpoint(method_name.to_s)
      begin
        endpoint.get
      rescue Errors::NotFound
        false
      else
        true
      end
    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