chubasaweber 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
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