apsis-on-steroids 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -3,7 +3,7 @@ source "http://rubygems.org"
3
3
  # Example:
4
4
  # gem "activesupport", ">= 2.3.5"
5
5
 
6
- gem "http2", ">= 0.0.16"
6
+ gem "http2", "~> 0.0.17"
7
7
  gem "string-cases"
8
8
 
9
9
  # Add dependencies to develop your gem here.
data/Gemfile.lock CHANGED
@@ -3,7 +3,7 @@ GEM
3
3
  specs:
4
4
  diff-lcs (1.1.3)
5
5
  git (1.2.5)
6
- http2 (0.0.16)
6
+ http2 (0.0.17)
7
7
  jeweler (1.8.4)
8
8
  bundler (~> 1.0)
9
9
  git (>= 1.2.5)
@@ -28,7 +28,7 @@ PLATFORMS
28
28
 
29
29
  DEPENDENCIES
30
30
  bundler (>= 1.0.0)
31
- http2 (>= 0.0.16)
31
+ http2 (~> 0.0.17)
32
32
  jeweler (~> 1.8.4)
33
33
  rdoc (~> 3.12)
34
34
  rspec (~> 2.8.0)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.3
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "apsis-on-steroids"
8
- s.version = "0.0.1"
8
+ s.version = "0.0.3"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["kaspernj"]
12
- s.date = "2013-06-21"
12
+ s.date = "2013-07-25"
13
13
  s.description = "A Ruby API for the Apsis mail service. "
14
14
  s.email = "k@spernj.org"
15
15
  s.extra_rdoc_files = [
@@ -43,14 +43,14 @@ Gem::Specification.new do |s|
43
43
  s.specification_version = 3
44
44
 
45
45
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
46
- s.add_runtime_dependency(%q<http2>, [">= 0.0.16"])
46
+ s.add_runtime_dependency(%q<http2>, ["~> 0.0.17"])
47
47
  s.add_runtime_dependency(%q<string-cases>, [">= 0"])
48
48
  s.add_development_dependency(%q<rspec>, ["~> 2.8.0"])
49
49
  s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
50
50
  s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
51
51
  s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
52
52
  else
53
- s.add_dependency(%q<http2>, [">= 0.0.16"])
53
+ s.add_dependency(%q<http2>, ["~> 0.0.17"])
54
54
  s.add_dependency(%q<string-cases>, [">= 0"])
55
55
  s.add_dependency(%q<rspec>, ["~> 2.8.0"])
56
56
  s.add_dependency(%q<rdoc>, ["~> 3.12"])
@@ -58,7 +58,7 @@ Gem::Specification.new do |s|
58
58
  s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
59
59
  end
60
60
  else
61
- s.add_dependency(%q<http2>, [">= 0.0.16"])
61
+ s.add_dependency(%q<http2>, ["~> 0.0.17"])
62
62
  s.add_dependency(%q<string-cases>, [">= 0"])
63
63
  s.add_dependency(%q<rspec>, ["~> 2.8.0"])
64
64
  s.add_dependency(%q<rdoc>, ["~> 3.12"])
@@ -1,57 +1,161 @@
1
+ require "uri"
2
+
1
3
  class ApsisOnSteroids::MailingList < ApsisOnSteroids::SubBase
2
4
  def create_subscribers(data)
3
- aos.req_json("v1/subscribers/mailinglist/#{data(:id)}/queue", :post, :json => data)
5
+ res = aos.req_json("v1/subscribers/mailinglist/#{data(:id)}/queue", :post, :json => data)
6
+
7
+ url = URI.parse(res["Result"]["PollURL"])
8
+ data_subscribers = nil
9
+
10
+ Timeout.timeout(300) do
11
+ loop do
12
+ sleep 1
13
+ res = aos.req_json(url.path)
14
+ debugs "Result: #{res}"
15
+
16
+ if res["State"] == "2"
17
+ data_url = URI.parse(res["DataUrl"])
18
+ data_subscribers = aos.req_json(data_url.path)
19
+ break
20
+ elsif res["State"] == "0" || res["State"] == "1"
21
+ # Keep waiting.
22
+ else
23
+ raise "Unknown state: '#{res["State"]}': #{res}."
24
+ end
25
+ end
26
+ end
27
+
28
+ data_subscribers
4
29
  end
5
30
 
6
31
  def subscribers
7
32
  res = aos.req_json("v1/mailinglists/#{data(:id)}/subscribers/all", :post, :json => {
8
- "AllDemographics" => true,
33
+ "AllDemographics" => false,
9
34
  "FieldNames" => []
10
35
  })
11
36
 
12
37
  url = URI.parse(res["Result"]["PollURL"])
38
+ data_subscribers = nil
13
39
 
14
- Timeout.timeout(30) do
40
+ Timeout.timeout(300) do
15
41
  loop do
16
- sleep 0.5
42
+ sleep 1
17
43
  res = aos.req_json(url.path)
18
44
 
19
- puts "Status res: #{res}"
20
-
21
45
  if res["State"] == "2"
46
+ data_url = URI.parse(res["DataUrl"])
47
+ data_subscribers = aos.req_json(data_url.path)
22
48
  break
49
+ elsif res["State"] == "0" || res["State"] == "1"
50
+ # Keep waiting.
51
+ else
52
+ raise "Unknown state: '#{res["State"]}': #{res}."
23
53
  end
24
54
  end
25
55
  end
56
+
57
+ data_subscribers.each do |sub_data|
58
+ sub = ApsisOnSteroids::Subscriber.new(
59
+ :aos => self.aos,
60
+ :data => aos.parse_obj(sub_data)
61
+ )
62
+
63
+ yield sub
64
+ end
65
+ end
66
+
67
+ # Adds the given email as a new subscriber and subscribes the created subscriber to the mailing list.
68
+ def subscriber_by_email(email)
69
+ sub = aos.subscriber_by_email(email)
70
+
71
+ res = aos.req_json("v1/subscribers/#{sub.data(:id)}/mailinglists")
72
+ if res["Result"]
73
+ mailinglist_ids = res["Result"]["Mailinglists"].map { |m| m["Id"].to_i }
74
+ return sub if mailinglist_ids.include?(self.data(:id))
75
+ end
26
76
 
27
- puts "Test: #{res}"
28
- raise "Finish me!"
77
+ raise "Could not find subscriber by that email: '#{email}' on this mailing list '#{self.data(:name)}'."
78
+ end
79
+
80
+ # Adds the given subscriber to the mailing list.
81
+ def add_subscriber(subscriber)
82
+ res = aos.req_json("v1/mailinglists/#{self.data(:id)}/subscriptions/#{subscriber.data(:id)}", :post)
83
+ if res["Message"] == "Succesfully created Subscription"
84
+ res["Result"].to_i > 0
85
+ else
86
+ raise "Unexpected result: '#{res["Result"]}'."
87
+ end
29
88
  end
30
89
 
90
+ # Removes the given subscriber from the mailing list.
31
91
  def remove_subscriber(subscriber)
32
92
  res = aos.req_json("v1/mailinglists/#{self.data(:id)}/subscriptions/#{subscriber.data(:id)}", :delete)
33
- if res["Result"] == "Deleted"
34
- return nil
93
+ if res["Message"] == "Successfully deleted Subscription"
94
+ true
35
95
  else
36
96
  raise "Unexpected result: '#{res["Result"]}'."
37
97
  end
38
98
  end
39
99
 
100
+ # Removes all subscribers from the mailing list.
101
+ def remove_all_subscribers
102
+ res = aos.req_json("v1/mailinglists/#{self.data(:id)}/subscriptions/all", :delete)
103
+ raise "Unexpected result: #{res}" if res["Code"] != 1
104
+ url = URI.parse(res["Result"]["PollURL"])
105
+ data = nil
106
+
107
+ Timeout.timeout(300) do
108
+ loop do
109
+ sleep 1
110
+
111
+ res = aos.req_json(url.path)
112
+
113
+ if res["State"] == "2"
114
+ url_data = URI.parse(res["DataUrl"])
115
+ data = aos.req_json(url_data.path)
116
+ break
117
+ elsif res["State"] == "0" || res["State"] == "1"
118
+ # Keep waiting.
119
+ else
120
+ raise "Unknown state '#{res["State"]}': #{res}"
121
+ end
122
+ end
123
+ end
124
+
125
+ return nil
126
+ end
127
+
128
+ # Returns true if the given subscriber is a member of the mailing list.
129
+ def member?(sub)
130
+ sub.mailing_lists.each do |mlist|
131
+ if mlist.data(:id) == self.data(:id)
132
+ return true
133
+ end
134
+ end
135
+
136
+ return false
137
+ end
138
+
139
+ # Deletes the mailing list from APSIS.
40
140
  def delete
41
141
  res = aos.req_json("v1/mailinglists/", :delete, :json => [data(:id)])
42
142
 
43
143
  url = URI.parse(res["Result"]["PollURL"])
44
144
  data = nil
45
145
 
46
- Timeout.timeout(30) do
146
+ Timeout.timeout(300) do
47
147
  loop do
48
- sleep 0.5
148
+ sleep 1
49
149
  res = aos.req_json(url.path)
50
150
 
51
151
  if res["State"] == "2"
52
152
  data_url = URI.parse(res["DataUrl"])
53
153
  data = aos.req_json(data_url.path)
54
154
  break
155
+ elsif res["State"] == "0" || res["State"] == "1"
156
+ # Keep waiting.
157
+ else
158
+ raise "Unknown state: '#{res["State"]}': #{res}"
55
159
  end
56
160
  end
57
161
  end
@@ -60,4 +164,4 @@ class ApsisOnSteroids::MailingList < ApsisOnSteroids::SubBase
60
164
  raise "Unexpected result: '#{data}'." if element["Value"] != "Succefully deleted"
61
165
  end
62
166
  end
63
- end
167
+ end
data/include/sub_base.rb CHANGED
@@ -15,11 +15,10 @@ class ApsisOnSteroids::SubBase
15
15
  def data(name)
16
16
  name = name.to_sym
17
17
  return @data[name] if @data.key?(name)
18
- raise "No such data: '#{name}'."
18
+ raise "No such data: '#{name}' in fields: #{@data.keys}"
19
19
  end
20
20
 
21
- def method_missing(name, *args, &blk)
22
- return @data[name.to_sym] if @data && @data.key?(name.to_sym)
23
- raise "No such method: '#{name}'."
21
+ def debugs(str)
22
+ self.aos.debugs(str)
24
23
  end
25
- end
24
+ end
@@ -24,14 +24,19 @@ class ApsisOnSteroids::Subscriber < ApsisOnSteroids::SubBase
24
24
  url = URI.parse(res["Result"]["PollURL"])
25
25
  data = nil
26
26
 
27
- Timeout.timeout(30) do
27
+ Timeout.timeout(300) do
28
28
  loop do
29
+ sleep 1
29
30
  res = aos.req_json(url.path)
30
31
 
31
32
  if res["State"] == "2"
32
33
  url_data = URI.parse(res["DataUrl"])
33
34
  data = aos.req_json(url_data.path)
34
35
  break
36
+ elsif res["State"] == "0" || res["State"] == "1"
37
+ # Keep waiting.
38
+ else
39
+ raise "Unknown state '#{res["State"]}': #{res}"
35
40
  end
36
41
  end
37
42
  end
@@ -39,4 +44,19 @@ class ApsisOnSteroids::Subscriber < ApsisOnSteroids::SubBase
39
44
  raise data["FailedUpdatedSubscribers"].to_s if data["FailedUpdatedSubscribers"] && data["FailedUpdatedSubscribers"].any?
40
45
  return nil
41
46
  end
47
+
48
+ # Returns an array of mailing lists that the sucscriber is subscribed to.
49
+ def mailing_lists
50
+ ret = []
51
+
52
+ res = aos.req_json("v1/subscribers/#{self.data(:id)}/mailinglists")
53
+ raise "Unexpected result: #{res}" if res["Code"] != 1 || !res["Result"].is_a?(Hash)
54
+
55
+ res["Result"]["Mailinglists"].each do |mlist_data|
56
+ mlist = ApsisOnSteroids::MailingList.new(:data => mlist_data, :aos => aos)
57
+ ret << mlist
58
+ end
59
+
60
+ return ret
61
+ end
42
62
  end
@@ -42,6 +42,16 @@ class ApsisOnSteroids
42
42
  end
43
43
  end
44
44
 
45
+ # Closes connection and removes all references to resource-objects.
46
+ def destroy
47
+ @http.destroy if @http
48
+ @http = nil
49
+ end
50
+
51
+ def debugs(str)
52
+ puts str if @args[:debug]
53
+ end
54
+
45
55
  def mailing_lists
46
56
  res = req_json("v1/mailinglists/1/999")
47
57
 
@@ -67,62 +77,19 @@ class ApsisOnSteroids
67
77
 
68
78
  def mailing_list_by_name(name)
69
79
  self.mailing_lists.each do |mlist|
70
- return mlist if name.to_s == mlist.name.to_s
80
+ return mlist if name.to_s == mlist.data(:name).to_s
71
81
  end
72
82
 
73
83
  raise "Could not find mailing list by that name: '#{name}'."
74
84
  end
75
-
76
- def subscribers
77
- # Request a list of all subs.
78
- res = req_json("v1/subscribers/all", :post, :json => {
79
- "AllDemographics" => true,
80
- "FieldNames" => []
81
- })
82
-
83
- # Wait for the server to generate the list.
84
- url = URI.parse(res["Result"]["PollURL"])
85
- data = nil
86
-
87
- Timeout.timeout(30) do
88
- loop do
89
- sleep 0.5
90
- res = req_json(url.path)
91
-
92
- if res["State"] == "2"
93
- url_data = URI.parse(res["DataUrl"])
94
- data = req_json(url_data.path)
95
- break
96
- end
97
- end
98
- end
99
85
 
100
- # Parse the list of subscribers.
101
- ret = [] unless block_given?
102
-
103
- data.each do |sub_data|
104
- sub = ApsisOnSteroids::Subscriber.new(
105
- :aos => self,
106
- :data => sub_data
107
- )
108
-
109
- if block_given?
110
- yield sub
111
- else
112
- ret << sub
113
- end
114
- end
115
-
116
- if block_given?
117
- return nil
118
- else
119
- return ret
86
+ def subscriber_by_email(email)
87
+ begin
88
+ res = req_json("v1/subscribers/email/lookup/#{CGI.escape(email)}")
89
+ rescue
90
+ raise "Could not find subscriber by that email in the system"
120
91
  end
121
- end
122
92
 
123
- def subscriber_by_email(email)
124
- res = req_json("v1/subscribers/email/lookup/#{CGI.escape(email)}")
125
-
126
93
  sub = ApsisOnSteroids::Subscriber.new(
127
94
  :aos => self,
128
95
  :data => {
@@ -136,7 +103,7 @@ class ApsisOnSteroids
136
103
 
137
104
  def req_json(url, type = :get, method_args = {})
138
105
  # Parse arguments, send and parse the result.
139
- args = {:url => url}.merge(method_args)
106
+ args = { :url => url.start_with?('/') ? url[1..-1] : url }.merge(method_args)
140
107
  http_res = @http.__send__(type, args)
141
108
 
142
109
  begin
@@ -152,4 +119,32 @@ class ApsisOnSteroids
152
119
  # Return the result.
153
120
  return res
154
121
  end
122
+
123
+ def parse_obj(obj)
124
+ if obj.is_a?(Array)
125
+ ret = []
126
+ obj.each do |obj_i|
127
+ ret << parse_obj(obj_i)
128
+ end
129
+
130
+ return ret
131
+ elsif obj.is_a?(Hash)
132
+ ret = {}
133
+ obj.each do |key, val|
134
+ ret[key] = parse_obj(val)
135
+ end
136
+
137
+ return ret
138
+ elsif obj.is_a?(String)
139
+ # Automatically convert dates.
140
+ if match = obj.match(/^\/Date\((\d+)\+(\d+)\)\//)
141
+ unix_t = match[1].to_i / 1000
142
+ return Time.at(unix_t)
143
+ end
144
+
145
+ return obj
146
+ else
147
+ return obj
148
+ end
149
+ end
155
150
  end
@@ -1,82 +1,115 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe "ApsisOnSteroids" do
4
- it "can connect" do
5
- $aos = ApsisOnSteroids.new(
4
+ let(:aos) do
5
+ ApsisOnSteroids.new(
6
6
  :api_key => File.read("#{File.dirname(__FILE__)}/api_key.txt").strip,
7
7
  :debug => false
8
8
  )
9
9
  end
10
+
11
+ it "can connect" do
12
+ aos
13
+ end
10
14
 
11
15
  it "should create and delete a mailing list" do
12
16
  name = "create-mlist-#{Time.now.to_f.to_s}"
13
17
 
14
- $aos.create_mailing_list(
18
+ aos.create_mailing_list(
15
19
  :Name => name,
16
20
  :FromName => "Kasper Johansen",
17
21
  :FromEmail => "kj@naoshi-dev.com",
18
22
  :CharacterSet => "utf-8"
19
23
  )
20
24
 
21
- mlist = $aos.mailing_list_by_name(name)
25
+ mlist = aos.mailing_list_by_name(name)
22
26
 
23
27
  sleep 1
24
28
  mlist.delete
25
29
  end
26
-
30
+
27
31
  it "can get a mailing list" do
28
- $mlist = $aos.mailing_list_by_name("kj")
29
- end
30
-
31
- it "can create subscribers" do
32
- $mlist.create_subscribers([{
33
- :Email => "kj@gfish.com",
34
- :Name => "Kasper Johansen"
35
- }])
36
- end
37
-
38
- it "can get subscribers and their details" do
39
- $sub = $aos.subscriber_by_email("kj@gfish.com")
40
- details = $sub.details
41
- details.is_a?(Hash).should eql(true)
42
- details.key?(:pending).should eql(false)
43
- end
44
-
45
- it "can update subscribers" do
46
- new_email = "kaspernj#{Time.now.to_f}@naoshi-dev.com"
47
- $sub.update(:Email => new_email)
48
- $sub.details[:Email].should eql(new_email)
49
- $sub.details[:Name].should eql("Kasper Johansen")
32
+ mlist = aos.mailing_list_by_name("kj")
50
33
  end
34
+
35
+ context do
36
+ let(:mlist) do
37
+ mlist = aos.mailing_list_by_name("kj")
38
+ mlist.remove_all_subscribers
39
+ mlist
40
+ end
41
+
42
+ let(:sub) do
43
+ email = "kaspernj#{Time.now.to_f}@naoshi-dev.com"
44
+ mlist.create_subscribers([{
45
+ :Email => email,
46
+ :Name => "Kasper Johansen"
47
+ }])
48
+ aos.subscriber_by_email(email)
49
+ end
51
50
 
52
- it "should not overwrite data when updating" do
53
- phone = Time.now.to_i.to_s
54
- $sub.update(:PhoneNumber => phone)
55
- $sub.details[:PhoneNumber].should eql(phone)
51
+ it "can create subscribers" do
52
+ sub
53
+ end
54
+
55
+ it "can get subscribers and their details" do
56
+ details = sub.details
57
+ details.is_a?(Hash).should eql(true)
58
+ details.key?(:pending).should eql(false)
59
+ end
60
+
61
+ it "can update subscribers" do
62
+ new_email = "kaspernj#{Time.now.to_f}-updated@naoshi-dev.com"
63
+ sub.update(:Email => new_email)
64
+ sleep 1
65
+ sub.details[:Email].should eql(new_email)
66
+ sub.details[:Name].should eql("Kasper Johansen")
67
+ end
68
+
69
+ it "should not overwrite data when updating" do
70
+ phone = Time.now.to_i.to_s
71
+ sub.update(:PhoneNumber => phone)
72
+ sub.details[:PhoneNumber].should eql(phone)
73
+
74
+ new_email = "kaspernj#{Time.now.to_f}-updated@naoshi-dev.com"
75
+ sub.update(:Email => new_email)
76
+ sub.details[:Email].should eql(new_email)
77
+
78
+ sub.details[:PhoneNumber].should eql(phone)
79
+ end
80
+
81
+ it "can lookup the subscriber on the list" do
82
+ mlist.subscriber_by_email(sub.data(:email)).should_not eq nil
83
+ end
56
84
 
57
- new_email = "kaspernj#{Time.now.to_f}@naoshi-dev.com"
58
- $sub.update(:Email => new_email)
59
- $sub.details[:Email].should eql(new_email)
85
+ it "can get lists of subscribers from lists" do
86
+ original_sub = sub
87
+
88
+ count = 0
89
+ mlist.subscribers do |sub_i|
90
+ count += 1
91
+ #puts "Subscriber: #{sub_i}"
92
+ end
93
+
94
+ raise "Expected more than one." if count <= 1
95
+ end
96
+
97
+ it "can remove subscribers from lists" do
98
+ mlist.remove_subscriber(sub)
99
+ end
100
+
101
+ it "can validate if a subscriber is active or not" do
102
+ sub.active?.should eql(true)
103
+ end
60
104
 
61
- $sub.details[:PhoneNumber].should eql(phone)
62
- end
63
-
64
- it "can remove subscribers from lists" do
65
- $mlist.remove_subscriber($sub)
66
- end
67
-
68
- it "can get lists of subscribers from lists" do
69
- $mlist.subscribers do |sub|
70
- puts "Subscriber: #{sub}"
105
+ it "can subscribe, remove and then re-subscribe" do
106
+ sub.active?.should eql(true)
107
+
108
+ mlist.remove_subscriber(sub)
109
+ mlist.add_subscriber(sub)
110
+
111
+ sub.active?.should eql(true)
112
+ mlist.member?(sub).should eql(true)
71
113
  end
72
114
  end
73
-
74
- it "can validate if a subscriber is active or not" do
75
- $sub.active?.should eql(true)
76
- end
77
-
78
- it "can get a list of all subscribers" do
79
- total_list = $aos.subscribers
80
- total_list.is_a?(Array).should eql(true)
81
- end
82
115
  end
metadata CHANGED
@@ -2,31 +2,31 @@
2
2
  name: apsis-on-steroids
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.1
5
+ version: 0.0.3
6
6
  platform: ruby
7
7
  authors:
8
8
  - kaspernj
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-21 00:00:00.000000000 Z
12
+ date: 2013-07-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  version_requirements: !ruby/object:Gem::Requirement
16
16
  none: false
17
17
  requirements:
18
- - - ! '>='
18
+ - - ~>
19
19
  - !ruby/object:Gem::Version
20
- version: 0.0.16
20
+ version: 0.0.17
21
21
  name: http2
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  requirement: !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
27
- - - ! '>='
27
+ - - ~>
28
28
  - !ruby/object:Gem::Version
29
- version: 0.0.16
29
+ version: 0.0.17
30
30
  - !ruby/object:Gem::Dependency
31
31
  version_requirements: !ruby/object:Gem::Requirement
32
32
  none: false
@@ -144,7 +144,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
144
144
  - !ruby/object:Gem::Version
145
145
  segments:
146
146
  - 0
147
- hash: -2130577314090490558
147
+ hash: -867617378324524175
148
148
  version: '0'
149
149
  required_rubygems_version: !ruby/object:Gem::Requirement
150
150
  none: false