office_autopilot_api 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c7d7c8092131eb0c00fdf8b4f6e6d0056d29489f
4
+ data.tar.gz: 4c13482acbab47bb54ef2df6207742c116516d92
5
+ SHA512:
6
+ metadata.gz: 88de50b2078e5548909f52f1d1496523c5eeacced13f025f7b2d2500acb27ed1722b8b9c9d67fe91945fa636f2c7ed2aea5131dcaa2ccf592916b7cd4942594a
7
+ data.tar.gz: d3143011e8bcc35c5b84f76305fc2b725fbb30f45c4e160c937837a4b9736551a85ecb70746660fa5c16b8dde26d2860bda82b73c16466c60d5551ff03400b81
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .bundle
3
+ .rvmrc
4
+ .idea
5
+ Gemfile.lock
6
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in office_autopilot.gemspec
4
+ gemspec
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Prashant Nadarajan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,71 @@
1
+ The OfficeAutopilot Ruby Gem
2
+ ============================
3
+ A Ruby wrapper for the OfficeAutopilot API
4
+
5
+ Installation
6
+ ------------
7
+ gem install office_autopilot_api
8
+
9
+ Usage Examples
10
+ --------------
11
+ require "rubygems"
12
+ require "office_autopilot_api"
13
+
14
+ client = OfficeAutopilotApi::Client.new(:api_id => 'xxx', :api_key => 'yyy')
15
+
16
+ # Search Contacts
17
+ puts client.contacts_search(:field => 'E-Mail', :op => 'e', :value => 'prashant@example.com')
18
+ # results truncated for brevity but ALL fields (including custom fields) are returned
19
+ => [{"id"=>"7",
20
+ "Contact Information"=>{"First Name"=>"testing", "Last Name"=>"testing", "E-Mail"=>"prashant@example.com"},
21
+ "Lead Information"=>{"Contact Owner"=>"XXX", "First Referrer"=>"", "Last Referrer"=>""},
22
+ "Sequences and Tags"=>{"Sequences"=>"*/*", "Contact Tags"=>""},
23
+ "Purchase History"=>{}
24
+ }]
25
+
26
+ # Add Contact
27
+ puts client.contacts_add({ 'Contact Information' => {'First Name' => 'Turtle', 'Last Name' => 'Jones', 'E-Mail' => 'mrturtles@example.com'} })
28
+ => {"id"=>"24", "Contact Information"=>{"First Name"=>"Turtle", "Last Name"=>"Jones", "E-Mail"=>"mrturtles@example.com"}}
29
+
30
+ Documentation
31
+ -------------
32
+
33
+ #### Currently supported API methods:
34
+
35
+ **Contacts:**
36
+
37
+ * contacts_search
38
+
39
+ * contacts_add
40
+
41
+ * contacts_pull_tag
42
+
43
+ * contacts_fetch_sequences
44
+
45
+ * contacts_key
46
+
47
+ * contacts_fetch
48
+
49
+
50
+ [**OfficeAutopilot API Docs**](http://wiki.sendpepper.com/w/page/19528683/API-Documentation)
51
+
52
+ Todo
53
+ ----
54
+
55
+ * support ALL API calls
56
+
57
+ Submitting a Pull Request
58
+ -------------------------
59
+ 1. Fork the project.
60
+ 2. Create a topic branch.
61
+ 3. Implement your feature or bug fix.
62
+ 4. Add documentation for your feature or bug fix.
63
+ 5. Add specs for your feature or bug fix.
64
+ 6. Run <tt>bundle exec rake spec</tt>. If your changes are not 100% covered, go back to step 5.
65
+ 7. Commit and push your changes.
66
+ 8. Submit a pull request. Please do not include changes to the gemspec or version file. (If you want to create your own version for some reason, please do so in a separate commit.)
67
+
68
+ Copyright
69
+ ---------
70
+ Copyright (c) 2011 Prashant Nadarajan.
71
+ See [LICENSE](https://github.com/parasquid/office_autopilot/blob/master/MIT_LICENSE) for details.
@@ -0,0 +1,8 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :test => :spec
8
+ task :default => :spec
@@ -0,0 +1 @@
1
+ require 'office_autopilot_api/client'
@@ -0,0 +1,51 @@
1
+ require 'builder'
2
+ require 'nokogiri'
3
+
4
+ require File.expand_path('../error', __FILE__)
5
+ require File.expand_path('../request', __FILE__)
6
+ require File.expand_path('../client/contacts', __FILE__)
7
+
8
+ module OfficeAutopilotApi
9
+ class Client
10
+
11
+ include Contacts
12
+
13
+ def initialize(options)
14
+ @api = {
15
+ :api_id => options[:api_id],
16
+ :api_key => options[:api_key]
17
+ }
18
+
19
+ raise ArgumentError, "Missing required parameter: api_id" if @api[:api_id].nil?
20
+ raise ArgumentError, "Missing required parameter: api_key" if @api[:api_key].nil?
21
+ end
22
+
23
+ def api_id
24
+ @api[:api_id]
25
+ end
26
+
27
+ def api_key
28
+ @api[:api_key]
29
+ end
30
+
31
+ def auth
32
+ { 'Appid' => api_id, 'Key' => api_key }
33
+ end
34
+
35
+ def request(method, path, options)
36
+ options[:body].merge!(auth)
37
+ handle_response( OfficeAutopilotApi::Request.send(method, path, options) )
38
+ end
39
+
40
+ def handle_response(response)
41
+ xml = Nokogiri::XML(response)
42
+
43
+ if xml.at_css('result').content =~ /failure/i
44
+ raise OfficeAutopilotApi::XmlError if xml.at_css('result error').content =~ /Invalid XML/i
45
+ end
46
+
47
+ response
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,160 @@
1
+ module OfficeAutopilotApi
2
+ class Client
3
+ module Contacts
4
+
5
+ CONTACTS_ENDPOINT = '/cdata.php'
6
+
7
+ def contacts_search(options)
8
+ xml = xml_for_search(options)
9
+ response = request(:post, CONTACTS_ENDPOINT, :body => {'reqType' => 'search', 'data' => xml})
10
+ parse_contacts_xml(response)
11
+ end
12
+
13
+ def contacts_add(options)
14
+ xml = xml_for_contact(options)
15
+ response = request(:post, CONTACTS_ENDPOINT, :body => {'reqType' => 'add', 'return_id' => '1', 'data' => xml})
16
+ parse_contacts_xml(response)[0]
17
+ end
18
+
19
+ def contacts_update(options)
20
+ xml = xml_for_contact(options)
21
+ response = request(:post, CONTACTS_ENDPOINT, :body => {'reqType' => 'update', 'return_id' => '1', 'data' => xml})
22
+ parse_contacts_xml(response)[0]
23
+ end
24
+
25
+ def contacts_pull_tag
26
+ response = request(:post, CONTACTS_ENDPOINT, :body => {'reqType' => 'pull_tag'})
27
+ parse_xml(response, "tag")
28
+ end
29
+
30
+ def contacts_fetch_sequences
31
+ response = request(:post, CONTACTS_ENDPOINT, :body => {'reqType' => 'fetch_sequences'})
32
+ parse_xml(response, "sequence")
33
+ end
34
+
35
+ def contacts_key
36
+ response = request(:post, CONTACTS_ENDPOINT, :body => {'reqType' => 'key'})
37
+ parse_contacts_key_xml(response)
38
+ end
39
+
40
+ def contacts_fetch(ids)
41
+ xml = xml_for_fetch("contact", ids)
42
+ response = request(:post, CONTACTS_ENDPOINT, :body => {'reqType' => 'fetch', 'data' => xml})
43
+ parse_contacts_xml(response)
44
+ end
45
+
46
+ private
47
+
48
+ def parse_contacts_xml(response)
49
+ contacts = []
50
+ xml = Nokogiri::XML(response)
51
+ xml.css('result contact').each do |node|
52
+ contact = {}
53
+ contact['id'] = node['id']
54
+
55
+ node.css('Group_Tag').each do |group_tag|
56
+ group_tag_name = group_tag['name']
57
+ contact[group_tag_name] = {}
58
+
59
+ group_tag.css('field').each do |field|
60
+ field_name = field['name']
61
+ contact[group_tag_name][field_name] = field.content
62
+ end
63
+ end
64
+ contacts << contact
65
+ end
66
+ contacts
67
+ end
68
+
69
+ def parse_contacts_key_xml(response)
70
+ groups = {}
71
+
72
+ xml = Nokogiri::XML(response)
73
+ xml.css('result contact Group_Tag').each do |group_tag|
74
+ group = { 'fields' => {} }
75
+ group['editable'] = group_tag['editable'] == '1'
76
+
77
+ group_tag.css('field').each do |field_node|
78
+ field_type = field_node['type']
79
+ field_info = { 'type' => field_type }
80
+ field_info['editable'] = field_node['editable'] == '1'
81
+
82
+ case field_type
83
+ when 'tdrop'
84
+ options = []
85
+ field_info['options'] = options
86
+ field_node.css('option').each do |option_node|
87
+ options << option_node.content
88
+ end
89
+ when 'list'
90
+ list = {}
91
+ field_info['list'] = list
92
+ field_node.css('list').each do |list_node|
93
+ list[list_node['id']] = list_node.content
94
+ end
95
+ end
96
+ group['fields'][field_node['name']] = field_info
97
+ end
98
+ groups[group_tag['name']] = group
99
+ end
100
+ groups
101
+ end
102
+
103
+ def parse_xml(response, element_name)
104
+ result = {}
105
+ xml = Nokogiri::XML(response)
106
+ xml.css("result #{element_name}").each do |node|
107
+ id = node['id']
108
+ result[id] = node.content
109
+ end
110
+ result
111
+ end
112
+
113
+ def xml_for_contact(options)
114
+ attrs = {}
115
+ id = options.delete('id')
116
+ attrs[:id] = id if id
117
+ action = options.delete('action')
118
+
119
+ xml = Builder::XmlMarkup.new
120
+ xml.contact(attrs) do
121
+ options.each_key do |group_tag|
122
+ xml.Group_Tag(:name => group_tag) do
123
+ options[group_tag].each do |field, value|
124
+ xml_params = {:name => field}
125
+ xml_params[:action] = action unless action.nil? || action.blank?
126
+ xml.field(value, xml_params)
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
132
+
133
+ def xml_for_fetch(type, ids)
134
+ xml = ""
135
+ ids.each do |id|
136
+ xml << "<#{type}_id>#{id}</#{type}_id>"
137
+ end
138
+ xml
139
+ end
140
+
141
+ def xml_for_search(options)
142
+ if options.is_a?(Hash)
143
+ options = [options]
144
+ end
145
+
146
+ xml = Builder::XmlMarkup.new
147
+ xml.search do
148
+ options.each do |option|
149
+ xml.equation do
150
+ xml.field option[:field]
151
+ xml.op option[:op]
152
+ xml.value option[:value]
153
+ end
154
+ end
155
+ end
156
+ end
157
+
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,7 @@
1
+ module OfficeAutopilotApi
2
+ # Custom error class for rescuing from all OfficeAutopilot errors
3
+ class Error < StandardError; end
4
+
5
+ # Raised when OfficeAutopilot returns <result>failure<error>Invalid XML</error></result>
6
+ class XmlError < Error; end
7
+ end
@@ -0,0 +1,11 @@
1
+ require 'httparty'
2
+
3
+ module OfficeAutopilotApi
4
+ class Request
5
+
6
+ include HTTParty
7
+ base_uri 'http://api.moon-ray.com'
8
+ format :plain
9
+
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module OfficeAutopilotApi
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "office_autopilot_api/version"
4
+
5
+ Gem::Specification.new do |s|
6
+
7
+ s.add_development_dependency('rake', '~> 0.8')
8
+ s.add_development_dependency('rspec', '~> 2.5')
9
+ s.add_development_dependency('webmock', '~> 1.6')
10
+
11
+ s.add_runtime_dependency('httparty', '~> 0.7')
12
+ s.add_runtime_dependency('builder', '>= 2.1.2')
13
+ s.add_runtime_dependency('nokogiri', '~> 1.4')
14
+
15
+ s.name = "office_autopilot_api"
16
+ s.version = OfficeAutopilotApi::VERSION
17
+ s.platform = Gem::Platform::RUBY
18
+ s.authors = ["Prashant Nadarajan", "parasquid"]
19
+ s.email = ["prashant.nadarajan@gmail.com", 'parasquid']
20
+ s.homepage = "https://github.com/parasquid/office_autopilot"
21
+ s.summary = %q{Ruby wrapper for the OfficeAutopilot API}
22
+ s.description = %q{A Ruby wrapper for the OfficeAutopilot API}
23
+
24
+ s.rubyforge_project = "office_autopilot_api"
25
+
26
+ s.files = `git ls-files`.split("\n")
27
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
28
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
29
+ s.require_paths = ["lib"]
30
+ end
@@ -0,0 +1,69 @@
1
+ <result>
2
+ <contact id='7' date='1299671887' dlm='1299674450' score='0.00' purl='prashant' bulk_mail='1'>
3
+ <Group_Tag name='Contact Information'>
4
+ <field name="First Name">prashant</field>
5
+ <field name="Last Name">nadarajan</field>
6
+ <field name="E-Mail">prashant@example.com</field>
7
+ <field name="Home Phone"/>
8
+ <field name="Title"/>
9
+ <field name="Office Phone"/>
10
+ <field name="Cell Phone"/>
11
+ <field name="Fax"/>
12
+ <field name="Address"/>
13
+ <field name="Company"/>
14
+ <field name="Address 2"/>
15
+ <field name="City"/>
16
+ <field name="State"/>
17
+ <field name="Zip Code"/>
18
+ <field name="Website "/>
19
+ <field name="Country"/>
20
+ <field name="Birthday"/>
21
+ </Group_Tag>
22
+ <Group_Tag name='Lead Information'>
23
+ <field name="Contact Owner">Don Corleone</field>
24
+ <field name="First Referrer"/>
25
+ <field name="Last Referrer"/>
26
+ <field name="Lead Source"/>
27
+ <field name="Campaign"/>
28
+ <field name="Ad"/>
29
+ <field name="Media"/>
30
+ </Group_Tag>
31
+ <Group_Tag name='Sequences and Tags'>
32
+ <field name="Sequences">*/*</field>
33
+ <field name="Contact Tags"/>
34
+ </Group_Tag>
35
+ <Group_Tag name='Purchase History'></Group_Tag>
36
+ <Group_Tag name='Most Recent Charge'>
37
+ <field name="Charge Amount">$0.00</field>
38
+ <field name="Charge Invoice #"/>
39
+ </Group_Tag>
40
+ <Group_Tag name='Affiliate Data'>
41
+ <field name="Affiliate Program"/>
42
+ <field name="Number of Sales"/>
43
+ <field name="$ Sales">$0.00</field>
44
+ <field name="Paypal E-mail"/>
45
+ <field name="Affiliate Paypal"/>
46
+ </Group_Tag>
47
+ <Group_Tag
48
+ name='Most Recent Invoice'>
49
+ <field name="Invoice #"/>
50
+ <field name="Total Invoice Amount">$0.00</field>
51
+ </Group_Tag>
52
+ <Group_Tag name='Lead Status'>
53
+ <field name="Lead Status"/>
54
+ <field name="Preferencia Contacto"/>
55
+ </Group_Tag>
56
+ <Group_Tag name='Credit Card'>
57
+ <field name="Card Type"/>
58
+ <field name="Card Expiration Month"/>
59
+ <field name="Charge Result"/>
60
+ <field name="Card Expiration Year"/>
61
+ <field name="Card Number (Last 4)"/>
62
+ <field name="Payment Center Link"/>
63
+ </Group_Tag>
64
+ <Group_Tag name='Invoices'></Group_Tag>
65
+ <Group_Tag name='Subscriptions and Payment Plans'></Group_Tag>
66
+ <Group_Tag name='Website Subscribers'></Group_Tag>
67
+ </contact>
68
+ <status>Success</status>
69
+ </result>