apsis-on-steroids 0.0.1 → 0.0.3

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/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