bronto 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +82 -0
- data/Rakefile +12 -0
- data/bronto.gemspec +23 -0
- data/lib/bronto.rb +36 -0
- data/lib/bronto/base.rb +198 -0
- data/lib/bronto/contact.rb +62 -0
- data/lib/bronto/delivery.rb +49 -0
- data/lib/bronto/field.rb +11 -0
- data/lib/bronto/filter.rb +36 -0
- data/lib/bronto/list.rb +62 -0
- data/lib/bronto/message.rb +36 -0
- data/lib/bronto/version.rb +3 -0
- data/lib/core_ext/array.rb +14 -0
- data/lib/core_ext/object.rb +34 -0
- data/lib/core_ext/string.rb +8 -0
- data/test/contact_test.rb +91 -0
- data/test/delivery_test.rb +98 -0
- data/test/field_test.rb +80 -0
- data/test/list_test.rb +136 -0
- data/test/message_test.rb +83 -0
- data/test/test_helper.rb +25 -0
- metadata +138 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
module Bronto
|
2
|
+
class Delivery < Base
|
3
|
+
attr_accessor :start, :message_id, :status, :type, :from_email, :from_name, :reply_email, :content, :recipients,
|
4
|
+
:fields, :authentication, :reply_tracking
|
5
|
+
|
6
|
+
# Finds contacts based on the `filter` (Bronto::Filter object).
|
7
|
+
# * `page_number` is the page of contacts to request. Bronto doesn't specify how many contacts are returned per page,
|
8
|
+
# only that you should keep increasing the number until no more contacts are returned.
|
9
|
+
# * `fields` can be an array of field IDs or an array of Field objects.
|
10
|
+
# * `include_lists` determines whether to include the list IDs each contact belongs to.
|
11
|
+
def self.find(filter = Bronto::Filter.new, page_number = 1, include_recipients = false, include_content = false)
|
12
|
+
body = { filter: filter.to_hash, page_number: page_number, include_recipients: include_recipients,
|
13
|
+
include_content: include_content }
|
14
|
+
|
15
|
+
resp = request(:read) do
|
16
|
+
soap.body = body
|
17
|
+
end
|
18
|
+
|
19
|
+
Array.wrap(resp[:return]).map { |hash| new(hash) }
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(options = {})
|
23
|
+
super(options)
|
24
|
+
self.recipients = []
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_hash
|
28
|
+
hash = {
|
29
|
+
id: id, start: start, message_id: message_id, type: type, from_email: from_email, from_name: from_name,
|
30
|
+
reply_email: reply_email, recipients: recipients, fields: fields, authentication: authentication,
|
31
|
+
reply_tracking: reply_tracking
|
32
|
+
}
|
33
|
+
hash.each { |k,v| hash.delete(k) if v.blank? }
|
34
|
+
hash
|
35
|
+
end
|
36
|
+
|
37
|
+
def add_recipient(*args)
|
38
|
+
type = id = nil
|
39
|
+
|
40
|
+
type, id = if args.is_a? Array and args.length == 2
|
41
|
+
args
|
42
|
+
else
|
43
|
+
[args.first.class.to_s.split("::").last.downcase, args.first.id]
|
44
|
+
end
|
45
|
+
|
46
|
+
self.recipients << { type: type, id: id }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/bronto/field.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# Represents a filter (which is actually a set of filters).
|
2
|
+
# For more information, see the [Bronto documentation](http://community.bronto.com/api/v4/filters).
|
3
|
+
|
4
|
+
module Bronto
|
5
|
+
class Filter
|
6
|
+
attr_accessor :type, :fields
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
self.fields = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_hash
|
13
|
+
hash = { type: type || "AND" }
|
14
|
+
hash.merge(fields)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Accepts two or three arguments:
|
18
|
+
# 1. Field name
|
19
|
+
# 2. (optional) The operator to use (only available for certain fields; see the filter documentation).
|
20
|
+
# 3. Value
|
21
|
+
def add_filter(*args)
|
22
|
+
raise ArgumentError, "wrong number of arguments (#{args.length} for 2..3)" if args.length != 2 and args.length != 3
|
23
|
+
|
24
|
+
field = args.shift.to_sym
|
25
|
+
self.fields[field] = [] unless self.fields.has_key?(field)
|
26
|
+
|
27
|
+
if args.length == 1
|
28
|
+
self.fields[field] << args.first
|
29
|
+
else
|
30
|
+
self.fields[field] << { operator: args.first, value: args.last }
|
31
|
+
end
|
32
|
+
|
33
|
+
self
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/bronto/list.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
module Bronto
|
2
|
+
class List < Base
|
3
|
+
attr_accessor :name, :label, :active_count, :status, :visibility
|
4
|
+
|
5
|
+
# Removes all contacts from the given lists.
|
6
|
+
def self.clear_lists(*lists)
|
7
|
+
resp = request(:clear) do
|
8
|
+
soap.body = {
|
9
|
+
list: lists.map { |l| { id: l.id } }
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
Array.wrap(resp[:return][:results]).select { |r| r[:is_error] }.count == 0
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(options = {})
|
17
|
+
super(options)
|
18
|
+
self.active_count ||= 0
|
19
|
+
end
|
20
|
+
|
21
|
+
# Adds the given contacts to this list.
|
22
|
+
def add_to_list(*contacts)
|
23
|
+
return false if !self.id.present?
|
24
|
+
|
25
|
+
# The block below is evaluated in a weird scope so we need to capture self as _self for use inside the block.
|
26
|
+
_self = self
|
27
|
+
|
28
|
+
resp = request("add_to_list") do
|
29
|
+
soap.body = {
|
30
|
+
list: { id: _self.id },
|
31
|
+
contacts: contacts.map { |c| { id: c.id } }
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
Array.wrap(resp[:return][:results]).select { |r| r[:is_error] }.count == 0
|
36
|
+
end
|
37
|
+
|
38
|
+
# Removes the given contacts from this list.
|
39
|
+
def remove_from_list(*contacts)
|
40
|
+
return false if !self.id.present?
|
41
|
+
|
42
|
+
resp = request("remove_from_list") do
|
43
|
+
soap.body = {
|
44
|
+
list: self.to_hash,
|
45
|
+
contacts: contacts.map(&:to_hash)
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
Array.wrap(resp[:return][:results]).select { |r| r[:is_error] }.count == 0
|
50
|
+
end
|
51
|
+
|
52
|
+
def active_count=(new_val)
|
53
|
+
@active_count = new_val.to_i
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_hash
|
57
|
+
hash = { name: name, label: label, status: status, visibility: visibility }
|
58
|
+
hash[:id] = id if id.present?
|
59
|
+
hash
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Bronto
|
2
|
+
class Message < Base
|
3
|
+
attr_accessor :name, :status, :message_folder_id, :content
|
4
|
+
|
5
|
+
def initialize(options = {})
|
6
|
+
super(options)
|
7
|
+
self.content = { }
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_hash
|
11
|
+
hash = { id: id, name: name, status: status, message_folder_id: message_folder_id, content: content.values.map(&:to_hash) }
|
12
|
+
[ :status, :id, :message_folder_id ].each do |f|
|
13
|
+
hash.delete(f) if send(f).blank?
|
14
|
+
end
|
15
|
+
hash
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_content(type, subject, content)
|
19
|
+
self.content[type] = Content.new(type, subject, content)
|
20
|
+
end
|
21
|
+
|
22
|
+
class Content
|
23
|
+
attr_accessor :type, :subject, :content
|
24
|
+
|
25
|
+
def initialize(type, subject, content)
|
26
|
+
self.type = type
|
27
|
+
self.subject = subject
|
28
|
+
self.content = content
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_hash
|
32
|
+
{ type: type, subject: subject, content: content }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class Array
|
2
|
+
unless self.respond_to? :wrap
|
3
|
+
# From: activesupport/lib/active_support/core_ext/array/wrap.rb, line 39
|
4
|
+
def self.wrap(object)
|
5
|
+
if object.nil?
|
6
|
+
[]
|
7
|
+
elsif object.respond_to?(:to_ary)
|
8
|
+
object.to_ary || [object]
|
9
|
+
else
|
10
|
+
[object]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Object
|
2
|
+
# From: activesupport/lib/active_support/core_ext/object/blank.rb, line 14
|
3
|
+
|
4
|
+
unless self.new.respond_to? :blank?
|
5
|
+
def blank?
|
6
|
+
respond_to?(:empty?) ? empty? : !self
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
unless self.new.respond_to? :present?
|
11
|
+
# From: activesupport/lib/active_support/core_ext/object/blank.rb, line 19
|
12
|
+
def present?
|
13
|
+
!blank?
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
unless self.new.respond_to? :try
|
18
|
+
# From: activesupport/lib/active_support/core_ext/object/try.rb, line 28
|
19
|
+
def try(*a, &b)
|
20
|
+
if a.empty? && block_given?
|
21
|
+
yield self
|
22
|
+
else
|
23
|
+
__send__(*a, &b)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class NilClass
|
30
|
+
# From: activesupport/lib/active_support/core_ext/object/try.rb, line 50
|
31
|
+
def try(*args)
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ContactTest < Test::Unit::TestCase
|
4
|
+
context "" do
|
5
|
+
setup do
|
6
|
+
@contact = Bronto::Contact.new(email: "#{Time.now.to_i}-#{rand(1000)}@example.com", status: "active")
|
7
|
+
end
|
8
|
+
|
9
|
+
teardown do
|
10
|
+
reset_all
|
11
|
+
end
|
12
|
+
|
13
|
+
should "create a new contact" do
|
14
|
+
assert_equal nil, @contact.id
|
15
|
+
|
16
|
+
@contact.save
|
17
|
+
|
18
|
+
assert_not_nil @contact.id
|
19
|
+
assert_equal 0, @contact.errors.count
|
20
|
+
end
|
21
|
+
|
22
|
+
should "get error on duplicate contact" do
|
23
|
+
@contact.save
|
24
|
+
|
25
|
+
c2 = Bronto::Contact.new(email: @contact.email)
|
26
|
+
c2.save
|
27
|
+
|
28
|
+
assert_equal nil, c2.id
|
29
|
+
assert_equal 1, c2.errors.count
|
30
|
+
assert_equal "305", c2.errors.messages.keys.first
|
31
|
+
end
|
32
|
+
|
33
|
+
should "destroy a contact" do
|
34
|
+
@contact.save
|
35
|
+
|
36
|
+
assert_nothing_raised do
|
37
|
+
@contact.destroy
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
should "find all contacts" do
|
42
|
+
@contact.save
|
43
|
+
|
44
|
+
contacts = Bronto::Contact.find
|
45
|
+
|
46
|
+
assert_equal 1, contacts.count
|
47
|
+
assert_equal @contact.id, contacts.first.id
|
48
|
+
|
49
|
+
c2 = Bronto::Contact.new(email: "#{Time.now.to_i}-#{rand(1000)}@example.com")
|
50
|
+
c2.save
|
51
|
+
|
52
|
+
assert_not_nil c2.id
|
53
|
+
|
54
|
+
contacts = Bronto::Contact.find
|
55
|
+
|
56
|
+
assert_equal 2, contacts.count
|
57
|
+
end
|
58
|
+
|
59
|
+
should "find a specific contact" do
|
60
|
+
@contact.save
|
61
|
+
|
62
|
+
filter = Bronto::Filter.new
|
63
|
+
filter.add_filter("email", "EndsWith", "example.com")
|
64
|
+
|
65
|
+
contacts = Bronto::Contact.find(filter)
|
66
|
+
|
67
|
+
assert_equal 1, contacts.count
|
68
|
+
assert_equal @contact.id, contacts.first.id
|
69
|
+
|
70
|
+
filter = Bronto::Filter.new
|
71
|
+
filter.add_filter("id", @contact.id)
|
72
|
+
|
73
|
+
contacts = Bronto::Contact.find(filter)
|
74
|
+
|
75
|
+
assert_equal 1, contacts.count
|
76
|
+
assert_equal @contact.id, contacts.first.id
|
77
|
+
end
|
78
|
+
|
79
|
+
should "include fields in results" do
|
80
|
+
f = Bronto::Field.new(name: "test_field", label: "Test Field", type: "text", visibility: "private")
|
81
|
+
f.save
|
82
|
+
|
83
|
+
@contact.set_field(f, "test value")
|
84
|
+
@contact.save
|
85
|
+
|
86
|
+
contacts = Bronto::Contact.find(Bronto::Filter.new, 1, [f.id], true)
|
87
|
+
assert_equal @contact.id, contacts.first.id
|
88
|
+
assert_equal "test value", contacts.first.get_field(f)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class DeliveryTest < Test::Unit::TestCase
|
4
|
+
context "" do
|
5
|
+
setup do
|
6
|
+
@message = Bronto::Message.new(name: "Test Message")
|
7
|
+
@message.add_content("html", "HTML Subject", "HTML Content")
|
8
|
+
@message.add_content("text", "Text Subject", "Text Content")
|
9
|
+
@message.save
|
10
|
+
|
11
|
+
@contact = Bronto::Contact.new(email: "#{Time.now.to_i}-#{rand(1000)}@example.com", status: "active")
|
12
|
+
@contact.save
|
13
|
+
|
14
|
+
@delivery = Bronto::Delivery.new(start: Time.now, type: "normal", from_name: "Hello", from_email: "test@example.com")
|
15
|
+
@delivery_2 = Bronto::Delivery.new(start: Time.now + (60 * 60 * 24 * 5), type: "normal", from_name: "Hello",
|
16
|
+
from_email: "test2@example.com")
|
17
|
+
end
|
18
|
+
|
19
|
+
teardown do
|
20
|
+
reset_all
|
21
|
+
end
|
22
|
+
|
23
|
+
should "create a new delivery" do
|
24
|
+
assert_equal nil, @delivery.id
|
25
|
+
|
26
|
+
@delivery.add_recipient(@contact)
|
27
|
+
@delivery.save
|
28
|
+
assert_equal "205", @delivery.errors.messages.keys.first
|
29
|
+
|
30
|
+
@delivery.message_id = @message.id
|
31
|
+
@delivery.save
|
32
|
+
|
33
|
+
assert_not_nil @delivery.id
|
34
|
+
assert_equal 0, @delivery.errors.count
|
35
|
+
end
|
36
|
+
|
37
|
+
should "destroy a delivery" do
|
38
|
+
skip "API says we should be able to delete a delivery, but well-formed message returns an error."
|
39
|
+
@delivery.message_id = @message.id
|
40
|
+
@delivery.save
|
41
|
+
|
42
|
+
assert_nothing_raised do
|
43
|
+
@delivery.destroy
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
should "find all deliveries" do
|
48
|
+
orig_delivery_count = Bronto::Delivery.find.count
|
49
|
+
|
50
|
+
@delivery.add_recipient(@contact)
|
51
|
+
@delivery.message_id = @message.id
|
52
|
+
@delivery.save
|
53
|
+
assert_not_nil @delivery.id
|
54
|
+
|
55
|
+
sleep(2)
|
56
|
+
|
57
|
+
deliveries = Bronto::Delivery.find
|
58
|
+
assert_equal orig_delivery_count + 1, deliveries.count
|
59
|
+
assert deliveries.any? { |d| d.id == @delivery.id }
|
60
|
+
|
61
|
+
@delivery_2.add_recipient(@contact)
|
62
|
+
@delivery_2.message_id = @message.id
|
63
|
+
@delivery_2.save
|
64
|
+
assert_not_nil @delivery_2.id
|
65
|
+
|
66
|
+
sleep(2)
|
67
|
+
|
68
|
+
deliveries = Bronto::Delivery.find
|
69
|
+
assert_equal orig_delivery_count + 2, deliveries.count
|
70
|
+
end
|
71
|
+
|
72
|
+
should "find a specific delivery" do
|
73
|
+
@delivery.add_recipient(@contact)
|
74
|
+
@delivery.message_id = @message.id
|
75
|
+
@delivery.save
|
76
|
+
|
77
|
+
@delivery_2.add_recipient(@contact)
|
78
|
+
@delivery_2.message_id = @message.id
|
79
|
+
@delivery_2.save
|
80
|
+
|
81
|
+
filter = Bronto::Filter.new
|
82
|
+
filter.add_filter("message_id", @message.id)
|
83
|
+
|
84
|
+
sleep(2)
|
85
|
+
|
86
|
+
deliveries = Bronto::Delivery.find(filter)
|
87
|
+
assert_equal 2, deliveries.count
|
88
|
+
|
89
|
+
filter = Bronto::Filter.new
|
90
|
+
filter.add_filter("id", @delivery.id)
|
91
|
+
|
92
|
+
deliveries = Bronto::Delivery.find(filter)
|
93
|
+
|
94
|
+
assert_equal 1, deliveries.count
|
95
|
+
assert deliveries.any? { |d| d.id == @delivery.id }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|