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.
Files changed (80) hide show
  1. data/.document +5 -0
  2. data/.gitignore +21 -0
  3. data/Gemfile +2 -0
  4. data/LICENSE +20 -0
  5. data/README.rdoc +17 -0
  6. data/README.textile +65 -0
  7. data/Rakefile +53 -0
  8. data/VERSION +1 -0
  9. data/aweber.gemspec +53 -0
  10. data/chubasaweber.gemspec +144 -0
  11. data/examples/with_access_token.rb +17 -0
  12. data/examples/your_account.rb +26 -0
  13. data/lib/aweber.rb +66 -0
  14. data/lib/aweber/base.rb +57 -0
  15. data/lib/aweber/collection.rb +110 -0
  16. data/lib/aweber/oauth.rb +69 -0
  17. data/lib/aweber/resource.rb +131 -0
  18. data/lib/aweber/resources.rb +14 -0
  19. data/lib/aweber/resources/account.rb +14 -0
  20. data/lib/aweber/resources/broadcast.rb +29 -0
  21. data/lib/aweber/resources/click.rb +13 -0
  22. data/lib/aweber/resources/followup.rb +24 -0
  23. data/lib/aweber/resources/integration.rb +8 -0
  24. data/lib/aweber/resources/link.rb +12 -0
  25. data/lib/aweber/resources/list.rb +86 -0
  26. data/lib/aweber/resources/message.rb +20 -0
  27. data/lib/aweber/resources/open.rb +10 -0
  28. data/lib/aweber/resources/subscriber.rb +28 -0
  29. data/lib/aweber/resources/tracked_event.rb +13 -0
  30. data/lib/aweber/resources/web_form.rb +14 -0
  31. data/lib/aweber/resources/web_form_split_test.rb +11 -0
  32. data/lib/aweber/resources/web_form_split_test_component.rb +20 -0
  33. data/lib/chubasaweber.rb +66 -0
  34. data/spec/base_spec.rb +23 -0
  35. data/spec/collection_spec.rb +40 -0
  36. data/spec/fixtures/account.json +8 -0
  37. data/spec/fixtures/accounts.json +13 -0
  38. data/spec/fixtures/campaign.json +23 -0
  39. data/spec/fixtures/campaigns.json +106 -0
  40. data/spec/fixtures/click.json +9 -0
  41. data/spec/fixtures/clicks.json +14 -0
  42. data/spec/fixtures/integration.json +8 -0
  43. data/spec/fixtures/integrations.json +45 -0
  44. data/spec/fixtures/link.json +10 -0
  45. data/spec/fixtures/links.json +75 -0
  46. data/spec/fixtures/list.json +11 -0
  47. data/spec/fixtures/lists.json +38 -0
  48. data/spec/fixtures/message.json +12 -0
  49. data/spec/fixtures/messages.json +29 -0
  50. data/spec/fixtures/open.json +8 -0
  51. data/spec/fixtures/opens.json +21 -0
  52. data/spec/fixtures/subscriber.json +16 -0
  53. data/spec/fixtures/subscribers.json +69 -0
  54. data/spec/fixtures/tracked_event.json +8 -0
  55. data/spec/fixtures/tracked_events.json +21 -0
  56. data/spec/fixtures/web_form.json +14 -0
  57. data/spec/fixtures/web_form_split_test.json +9 -0
  58. data/spec/fixtures/web_form_split_test_component.json +16 -0
  59. data/spec/fixtures/web_form_split_test_components.json +37 -0
  60. data/spec/fixtures/web_form_split_tests.json +41 -0
  61. data/spec/fixtures/web_forms.json +229 -0
  62. data/spec/oauth_spec.rb +96 -0
  63. data/spec/resource_spec.rb +80 -0
  64. data/spec/resources/account_spec.rb +13 -0
  65. data/spec/resources/campaign_spec.rb +14 -0
  66. data/spec/resources/click_spec.rb +14 -0
  67. data/spec/resources/integration_spec.rb +13 -0
  68. data/spec/resources/link_spec.rb +15 -0
  69. data/spec/resources/list_spec.rb +26 -0
  70. data/spec/resources/message_spec.rb +17 -0
  71. data/spec/resources/open_spec.rb +13 -0
  72. data/spec/resources/subscriber_spec.rb +33 -0
  73. data/spec/resources/tracked_event_spec.rb +14 -0
  74. data/spec/resources/web_form_spec.rb +19 -0
  75. data/spec/resources/web_form_split_test_component_spec.rb +20 -0
  76. data/spec/resources/web_form_split_test_spec.rb +14 -0
  77. data/spec/spec_helper.rb +52 -0
  78. data/test/helper.rb +10 -0
  79. data/test/test_chubasaweber.rb +7 -0
  80. metadata +181 -0
@@ -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
@@ -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
@@ -0,0 +1,13 @@
1
+ module AWeber
2
+ module Resources
3
+ class Click < Resource
4
+ api_attr :event_time
5
+ api_attr :is_earliest
6
+ api_attr :subscriber_link
7
+
8
+ has_one :subscriber
9
+
10
+ alias_attribute :is_earliest?, :is_earliest
11
+ end
12
+ end
13
+ end