chubasaweber 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/Gemfile +2 -0
- data/LICENSE +20 -0
- data/README.rdoc +17 -0
- data/README.textile +65 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/aweber.gemspec +53 -0
- data/chubasaweber.gemspec +144 -0
- data/examples/with_access_token.rb +17 -0
- data/examples/your_account.rb +26 -0
- data/lib/aweber.rb +66 -0
- data/lib/aweber/base.rb +57 -0
- data/lib/aweber/collection.rb +110 -0
- data/lib/aweber/oauth.rb +69 -0
- data/lib/aweber/resource.rb +131 -0
- data/lib/aweber/resources.rb +14 -0
- data/lib/aweber/resources/account.rb +14 -0
- data/lib/aweber/resources/broadcast.rb +29 -0
- data/lib/aweber/resources/click.rb +13 -0
- data/lib/aweber/resources/followup.rb +24 -0
- data/lib/aweber/resources/integration.rb +8 -0
- data/lib/aweber/resources/link.rb +12 -0
- data/lib/aweber/resources/list.rb +86 -0
- data/lib/aweber/resources/message.rb +20 -0
- data/lib/aweber/resources/open.rb +10 -0
- data/lib/aweber/resources/subscriber.rb +28 -0
- data/lib/aweber/resources/tracked_event.rb +13 -0
- data/lib/aweber/resources/web_form.rb +14 -0
- data/lib/aweber/resources/web_form_split_test.rb +11 -0
- data/lib/aweber/resources/web_form_split_test_component.rb +20 -0
- data/lib/chubasaweber.rb +66 -0
- data/spec/base_spec.rb +23 -0
- data/spec/collection_spec.rb +40 -0
- data/spec/fixtures/account.json +8 -0
- data/spec/fixtures/accounts.json +13 -0
- data/spec/fixtures/campaign.json +23 -0
- data/spec/fixtures/campaigns.json +106 -0
- data/spec/fixtures/click.json +9 -0
- data/spec/fixtures/clicks.json +14 -0
- data/spec/fixtures/integration.json +8 -0
- data/spec/fixtures/integrations.json +45 -0
- data/spec/fixtures/link.json +10 -0
- data/spec/fixtures/links.json +75 -0
- data/spec/fixtures/list.json +11 -0
- data/spec/fixtures/lists.json +38 -0
- data/spec/fixtures/message.json +12 -0
- data/spec/fixtures/messages.json +29 -0
- data/spec/fixtures/open.json +8 -0
- data/spec/fixtures/opens.json +21 -0
- data/spec/fixtures/subscriber.json +16 -0
- data/spec/fixtures/subscribers.json +69 -0
- data/spec/fixtures/tracked_event.json +8 -0
- data/spec/fixtures/tracked_events.json +21 -0
- data/spec/fixtures/web_form.json +14 -0
- data/spec/fixtures/web_form_split_test.json +9 -0
- data/spec/fixtures/web_form_split_test_component.json +16 -0
- data/spec/fixtures/web_form_split_test_components.json +37 -0
- data/spec/fixtures/web_form_split_tests.json +41 -0
- data/spec/fixtures/web_forms.json +229 -0
- data/spec/oauth_spec.rb +96 -0
- data/spec/resource_spec.rb +80 -0
- data/spec/resources/account_spec.rb +13 -0
- data/spec/resources/campaign_spec.rb +14 -0
- data/spec/resources/click_spec.rb +14 -0
- data/spec/resources/integration_spec.rb +13 -0
- data/spec/resources/link_spec.rb +15 -0
- data/spec/resources/list_spec.rb +26 -0
- data/spec/resources/message_spec.rb +17 -0
- data/spec/resources/open_spec.rb +13 -0
- data/spec/resources/subscriber_spec.rb +33 -0
- data/spec/resources/tracked_event_spec.rb +14 -0
- data/spec/resources/web_form_spec.rb +19 -0
- data/spec/resources/web_form_split_test_component_spec.rb +20 -0
- data/spec/resources/web_form_split_test_spec.rb +14 -0
- data/spec/spec_helper.rb +52 -0
- data/test/helper.rb +10 -0
- data/test/test_chubasaweber.rb +7 -0
- metadata +181 -0
data/lib/aweber/base.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
module AWeber
|
2
|
+
class Base
|
3
|
+
|
4
|
+
def initialize(oauth)
|
5
|
+
@oauth = oauth
|
6
|
+
end
|
7
|
+
|
8
|
+
def account
|
9
|
+
accounts.first.last
|
10
|
+
end
|
11
|
+
|
12
|
+
def get(uri)
|
13
|
+
response = oauth.get(expand(uri))
|
14
|
+
handle_errors(response, uri)
|
15
|
+
parse(response) if response
|
16
|
+
end
|
17
|
+
|
18
|
+
def delete(uri)
|
19
|
+
oauth.delete(expand(uri))
|
20
|
+
end
|
21
|
+
|
22
|
+
def put(uri, body={})
|
23
|
+
oauth.put(uri, body.to_json, {"Content-Type" => "application/json"})
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def handle_errors(response, uri)
|
29
|
+
if response.is_a? Net::HTTPNotFound
|
30
|
+
raise NotFoundError, "Invalid resource uri.", caller
|
31
|
+
elsif response && response.body == "NotAuthorizedError"
|
32
|
+
raise OAuthError, "Could not authorize OAuth credentials.", caller
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def accounts
|
37
|
+
@accounts ||= Collection.new(self, Resources::Account, get("/accounts"))
|
38
|
+
end
|
39
|
+
|
40
|
+
def expand(uri)
|
41
|
+
parsed = URI.parse(uri)
|
42
|
+
url = []
|
43
|
+
url << AWeber.api_endpoint
|
44
|
+
url << API_VERSION unless parsed.path.include? API_VERSION
|
45
|
+
url << parsed.path
|
46
|
+
File.join(*url)
|
47
|
+
end
|
48
|
+
|
49
|
+
def parse(response)
|
50
|
+
ActiveSupport::JSON.decode(response.body)
|
51
|
+
end
|
52
|
+
|
53
|
+
def oauth
|
54
|
+
@oauth
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module AWeber
|
2
|
+
# Collection objects are groups of Resources. Collections imitate
|
3
|
+
# regular Hashes in most ways. You can access Resource by +id+ via the
|
4
|
+
# +[]+ method.
|
5
|
+
#
|
6
|
+
# lists #=> #<AWeber::Collection ...>
|
7
|
+
# lists[1] #=> #<AWeber::Resources::List @id=1 ...>
|
8
|
+
#
|
9
|
+
# Also like Hashes, you can iterate over all of it's entries
|
10
|
+
#
|
11
|
+
# lists.each { |id, list| puts list.name }
|
12
|
+
#
|
13
|
+
# Collections support dynamic +find_by_*+ methods, where +*+ is an
|
14
|
+
# attribute and the first and only parameter is the value.
|
15
|
+
#
|
16
|
+
# lists.find_by_name("testlist")
|
17
|
+
# #=> #<AWeber::Resources::List @id=123, @name="testlist" ...>
|
18
|
+
#
|
19
|
+
# +find_by_*+ methods will also return a Hash of entries if more than
|
20
|
+
# one matches the criteria. The hash will be keyed by resource ID.
|
21
|
+
#
|
22
|
+
# messages.find_by_total_opens(0)
|
23
|
+
# #=> { "45697" => #<Message>, "12345" => #<Message> }
|
24
|
+
#
|
25
|
+
# Collections are paginated in groups of 20.
|
26
|
+
#
|
27
|
+
class Collection < Resource
|
28
|
+
include Enumerable
|
29
|
+
|
30
|
+
attr_reader :entries
|
31
|
+
attr_reader :next_collection_link
|
32
|
+
attr_reader :prev_collection_link
|
33
|
+
attr_reader :resource_type_link
|
34
|
+
attr_reader :total_size
|
35
|
+
|
36
|
+
alias_method :size, :total_size
|
37
|
+
alias_method :length, :total_size
|
38
|
+
|
39
|
+
# @param [AWeber::Base] client Instance of AWeber::Base
|
40
|
+
# @param [Class] klass Class to create entries of
|
41
|
+
# @param [Hash] data JSON decoded response data Hash
|
42
|
+
#
|
43
|
+
def initialize(client, klass, data={})
|
44
|
+
super client, data
|
45
|
+
@client = client
|
46
|
+
@klass = klass
|
47
|
+
@entries = {}
|
48
|
+
create_entries(data["entries"])
|
49
|
+
@_entries = @entries.to_a
|
50
|
+
end
|
51
|
+
|
52
|
+
def [](id)
|
53
|
+
@entries[id] ||= fetch_entry(id)
|
54
|
+
end
|
55
|
+
|
56
|
+
def each
|
57
|
+
(1..@total_size).each { |n| yield get_entry(n) }
|
58
|
+
end
|
59
|
+
|
60
|
+
def inspect
|
61
|
+
"#<AW::Collection(#{@klass.to_s}) size=\"#{size}\">"
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def create_entries(entries)
|
67
|
+
entries.each { |entry| @entries[entry["id"]] = @klass.new(client, entry) }
|
68
|
+
end
|
69
|
+
|
70
|
+
def get_entry(n)
|
71
|
+
@_entries += fetch_next_group if needs_next_group?(n)
|
72
|
+
@_entries[n-1]
|
73
|
+
end
|
74
|
+
|
75
|
+
def fetch_entry(id)
|
76
|
+
@klass.new(client, get(File.join(base_path, id.to_s)))
|
77
|
+
end
|
78
|
+
|
79
|
+
def fetch_next_group(amount=20)
|
80
|
+
path = "#{ base_path }?ws.start=#{ @_entries.size }&ws.size=#{ amount }"
|
81
|
+
self.class.new(client, @klass, get(path)).entries.to_a
|
82
|
+
end
|
83
|
+
|
84
|
+
def needs_next_group?(current_index)
|
85
|
+
current_index == @_entries.size && current_index != @total_size
|
86
|
+
end
|
87
|
+
|
88
|
+
def base_path
|
89
|
+
URI.parse(@next_collection_link).path
|
90
|
+
end
|
91
|
+
|
92
|
+
def find_by(_attr, *args)
|
93
|
+
matches = select { |id, e| e.send(_attr) == args.first }
|
94
|
+
matches = matches.first.last if matches.size == 1
|
95
|
+
matches
|
96
|
+
end
|
97
|
+
|
98
|
+
def method_missing(method, *args)
|
99
|
+
method.to_s.scan /^find_by_(.+)/ do |_attr|
|
100
|
+
return find_by(_attr.first, *args)
|
101
|
+
end
|
102
|
+
super
|
103
|
+
end
|
104
|
+
|
105
|
+
def client
|
106
|
+
@client
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
end
|
data/lib/aweber/oauth.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
module AWeber
|
2
|
+
class OAuth
|
3
|
+
extend Forwardable
|
4
|
+
|
5
|
+
def_delegators :access_token, :get, :post, :put, :delete
|
6
|
+
|
7
|
+
attr_accessor :callback_url
|
8
|
+
|
9
|
+
def initialize(consumer_token, consumer_secret, options={})
|
10
|
+
@consumer_token = consumer_token
|
11
|
+
@consumer_secret = consumer_secret
|
12
|
+
@callback_url = options[:callback_url]
|
13
|
+
end
|
14
|
+
|
15
|
+
def consumer
|
16
|
+
@consumer ||= ::OAuth::Consumer.new(@consumer_token, @consumer_secret, {
|
17
|
+
:site => AWeber.auth_endpoint,
|
18
|
+
:request_token_path => "/#{AWeber::AUTH_VERSION}/oauth/request_token",
|
19
|
+
:authorize_path => "/#{AWeber::AUTH_VERSION}/oauth/authorize",
|
20
|
+
:access_token_path => "/#{AWeber::AUTH_VERSION}/oauth/access_token",
|
21
|
+
:scheme => :query_string
|
22
|
+
})
|
23
|
+
end
|
24
|
+
|
25
|
+
# Retrieve a Request Token or simply return it, if it already exists.
|
26
|
+
#
|
27
|
+
# @param [Hash] options OAuth parameters. +:oauth_callback+ for example
|
28
|
+
#
|
29
|
+
def request_token(options={})
|
30
|
+
@request_token ||= consumer.get_request_token(options)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Get an Access Token from a Request Token using the
|
34
|
+
# +verifier+ code.
|
35
|
+
#
|
36
|
+
# @param [String] verifier Verification code retrieved from
|
37
|
+
# user authentication
|
38
|
+
#
|
39
|
+
def authorize_with_verifier(verifier)
|
40
|
+
token = request_token.get_access_token(:oauth_verifier => verifier)
|
41
|
+
@access_token_key = token.token
|
42
|
+
@access_token_secret = token.secret
|
43
|
+
access_token
|
44
|
+
end
|
45
|
+
|
46
|
+
def access_token
|
47
|
+
@access_token ||= ::OAuth::AccessToken.new(consumer, @access_token_key,
|
48
|
+
@access_token_secret)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Authorize with an Access Token key and secret you've previously
|
52
|
+
# retrieved via a user authentication.
|
53
|
+
#
|
54
|
+
# @param [String] access_token_key Access Token key
|
55
|
+
# @param [String] access_token_secret Access Token secret
|
56
|
+
#
|
57
|
+
def authorize_with_access(access_token_key, access_token_secret)
|
58
|
+
@access_token_key = access_token_key
|
59
|
+
@access_token_secret = access_token_secret
|
60
|
+
end
|
61
|
+
|
62
|
+
# Remove any active token instances and start over
|
63
|
+
#
|
64
|
+
def clear_tokens
|
65
|
+
@request_token = nil
|
66
|
+
@access_token = nil
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
module AWeber
|
2
|
+
# Base class for all entries. All resources have the following attributes:
|
3
|
+
#
|
4
|
+
# - +id+
|
5
|
+
# - +http_etag+ (aliased as +etag+)
|
6
|
+
# - +self_link+ (aliased as +link+)
|
7
|
+
# - +resource_type_link+ (aliased as +resource_type+)
|
8
|
+
#
|
9
|
+
# Resources also have attributes based on their the type of resource it is.
|
10
|
+
# To see a full list of attributes per resource, visit
|
11
|
+
# http://labs.aweber.com/docs/reference/1.0/reference.
|
12
|
+
#
|
13
|
+
class Resource
|
14
|
+
extend Forwardable
|
15
|
+
include Comparable
|
16
|
+
|
17
|
+
class << self
|
18
|
+
attr_accessor :writable_attrs
|
19
|
+
# Works the same as +alias_method+, but for attributes created via
|
20
|
+
# +attr*+ methods.
|
21
|
+
#
|
22
|
+
def alias_attribute(alias_, attribute)
|
23
|
+
alias_method alias_, attribute
|
24
|
+
end
|
25
|
+
|
26
|
+
# Defines an attribute that it either read only or writable.
|
27
|
+
#
|
28
|
+
# == Example:
|
29
|
+
#
|
30
|
+
# # Read-only
|
31
|
+
# api_attr :name
|
32
|
+
#
|
33
|
+
# # Writable
|
34
|
+
# api_attr :name, :writable => true
|
35
|
+
#
|
36
|
+
# If an attribute is writable it will be sent with the request when
|
37
|
+
# +save+ is called.
|
38
|
+
#
|
39
|
+
def api_attr(attr_, opts={})
|
40
|
+
if opts[:writable]
|
41
|
+
attr_accessor attr_
|
42
|
+
@writable_attrs ||= []
|
43
|
+
@writable_attrs << attr_
|
44
|
+
else
|
45
|
+
attr_reader attr_
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def has_one(name)
|
50
|
+
define_method(name) do
|
51
|
+
ivar = instance_variable_get("@#{name}")
|
52
|
+
return ivar if ivar
|
53
|
+
|
54
|
+
resource_link = instance_variable_get("@#{name}_link")
|
55
|
+
klass = AWeber.get_class(:"#{name}s")
|
56
|
+
collection = klass.new(client, client.get(resource_link))
|
57
|
+
instance_variable_set("@#{name}", collection)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Creates a lazy loaded method which will retrieve and create a
|
62
|
+
# collection of +name+ of objects.
|
63
|
+
#
|
64
|
+
# @param [Symbol] name name of the collection method
|
65
|
+
# @return [AWeber::Collection] Collection of +name+ objects
|
66
|
+
#
|
67
|
+
# @example
|
68
|
+
# class Account
|
69
|
+
# attr_reader :lists_collection_link
|
70
|
+
# collection :lists
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
# #=> Account.new(...).lists #=> <AWeber::Collection>
|
74
|
+
#
|
75
|
+
def has_many(name)
|
76
|
+
define_method(name) do
|
77
|
+
ivar = instance_variable_get("@#{name}")
|
78
|
+
return ivar if ivar
|
79
|
+
|
80
|
+
resource_link = instance_variable_get("@#{name}_collection_link")
|
81
|
+
klass = AWeber.get_class(name)
|
82
|
+
collection = Collection.new(client, klass, client.get(resource_link))
|
83
|
+
instance_variable_set("@#{name}", collection)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
api_attr :id
|
89
|
+
api_attr :http_etag
|
90
|
+
api_attr :self_link
|
91
|
+
api_attr :resource_type_link
|
92
|
+
|
93
|
+
alias_attribute :etag, :http_etag
|
94
|
+
alias_attribute :link, :self_link
|
95
|
+
alias_attribute :resource_type, :resource_type_link
|
96
|
+
|
97
|
+
def initialize(client, data={})
|
98
|
+
@client = client
|
99
|
+
data.each do |key, value|
|
100
|
+
instance_variable_set("@#{key}", value) if respond_to? key
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def delete
|
105
|
+
client.delete(@self_link)
|
106
|
+
end
|
107
|
+
|
108
|
+
def save
|
109
|
+
body = writable_attrs.inject({}) do |body, attr_|
|
110
|
+
body[attr_] = send(attr_)
|
111
|
+
body
|
112
|
+
end
|
113
|
+
client.put(self_link, body)
|
114
|
+
end
|
115
|
+
|
116
|
+
def writable_attrs
|
117
|
+
self.class.writable_attrs ||= {}
|
118
|
+
end
|
119
|
+
|
120
|
+
def <=>(other)
|
121
|
+
@id <=> other.id
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
def client
|
127
|
+
@client
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "aweber/resources/account"
|
2
|
+
require "aweber/resources/broadcast"
|
3
|
+
require "aweber/resources/click"
|
4
|
+
require "aweber/resources/followup"
|
5
|
+
require "aweber/resources/link"
|
6
|
+
require "aweber/resources/list"
|
7
|
+
require "aweber/resources/message"
|
8
|
+
require "aweber/resources/open"
|
9
|
+
require "aweber/resources/subscriber"
|
10
|
+
require "aweber/resources/tracked_event"
|
11
|
+
require "aweber/resources/integration"
|
12
|
+
require "aweber/resources/web_form"
|
13
|
+
require "aweber/resources/web_form_split_test"
|
14
|
+
require "aweber/resources/web_form_split_test_component"
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module AWeber
|
2
|
+
module Resources
|
3
|
+
class Account < Resource
|
4
|
+
api_attr :lists_collection_link
|
5
|
+
api_attr :integrations_collection_link
|
6
|
+
|
7
|
+
has_many :lists
|
8
|
+
has_many :integrations
|
9
|
+
|
10
|
+
alias_attribute :etag, :http_etag
|
11
|
+
alias_attribute :uri, :self_link
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module AWeber
|
2
|
+
module Resources
|
3
|
+
class Broadcast < Resource
|
4
|
+
api_attr :click_tracking_enabled
|
5
|
+
api_attr :content_type
|
6
|
+
api_attr :is_archived
|
7
|
+
api_attr :scheduled_at
|
8
|
+
api_attr :sent_at
|
9
|
+
api_attr :spam_assassin_score
|
10
|
+
api_attr :subject
|
11
|
+
api_attr :total_clicks
|
12
|
+
api_attr :total_opens
|
13
|
+
api_attr :total_sent
|
14
|
+
api_attr :total_spam_complaints
|
15
|
+
api_attr :total_undelivered
|
16
|
+
api_attr :total_unsubscribes
|
17
|
+
api_attr :twitter_account_link
|
18
|
+
|
19
|
+
api_attr :links_collection_link
|
20
|
+
api_attr :messages_collection_link
|
21
|
+
|
22
|
+
has_many :links
|
23
|
+
has_many :messages
|
24
|
+
|
25
|
+
alias_attribute :is_archived?, :is_archived
|
26
|
+
alias_attribute :is_click_tracking_enabled?, :click_tracking_enabled
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|