oas 0.1.0

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/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .bundle
3
+ .redcar
4
+ .rvmrc
5
+ Gemfile.lock
6
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in ruby-oas.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Realmedia LatinAmerica
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.
data/README.markdown ADDED
@@ -0,0 +1,69 @@
1
+ OAS API Ruby Gem
2
+ ====================
3
+ A Ruby wrapper for OAS 7.4 API
4
+
5
+ Installation
6
+ ------------
7
+ gem install oas
8
+
9
+ Usage Examples
10
+ --------------
11
+ require "rubygems"
12
+ require "oas"
13
+
14
+ # All methods require authentication.
15
+ Oas.configure do |config|
16
+ config.endpoint = WSDL_URI
17
+ config.account = YOUR_OAS_ACCOUNT
18
+ config.username = YOUR_USERNAME
19
+ config.password = YOUR_PASSWORD
20
+ end
21
+
22
+ # Read an advertiser
23
+ puts Oas.advertiser("advertiser_id")
24
+
25
+ # Read an agency
26
+ puts Oas.agency("agency_id")
27
+
28
+ # Read a campaign
29
+ puts Oas.campaign("campaign_id")
30
+
31
+ # Read a campaign group
32
+ puts Oas.campaign_group("campaign_group_id")
33
+
34
+ # Read a creative
35
+ puts Oas.creative("campaign_id", "creative_id")
36
+
37
+ # Read a keyname
38
+ puts Oas.keyname("keyname")
39
+
40
+ # Read a keyword
41
+ puts Oas.keyword("keyword_id")
42
+
43
+ # Read a notification
44
+ puts Oas.notification("campaign_id", "event_name")
45
+
46
+ # Read a page
47
+ puts Oas.page("page_url")
48
+
49
+ # Read a section
50
+ puts Oas.section("section_id")
51
+
52
+ # Read a site
53
+ puts Oas.site("site_id")
54
+
55
+ # Read a site group
56
+ puts Oas.site_group("site_group_id")
57
+
58
+ TODO
59
+ ------------
60
+
61
+ * Create and update support on Campaign and Database sections.
62
+ * Listings
63
+ * Reports
64
+ * Inventory
65
+
66
+ Copyright
67
+ ---------
68
+ Copyright (c) 2011 Realmedia LatinAmerica.
69
+ See [LICENSE](https://github.com/realmedia/ruby-oas/blob/master/LICENSE) for details.
data/Rakefile ADDED
@@ -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
data/lib/oas/api.rb ADDED
@@ -0,0 +1,56 @@
1
+ require 'nokogiri'
2
+ require 'httpclient'
3
+ require 'savon'
4
+
5
+ module Oas
6
+ class Api
7
+ attr_accessor *Configuration::VALID_OPTIONS_KEYS
8
+
9
+ def initialize(options={})
10
+ options = Oas.options.merge(options)
11
+ Configuration::VALID_OPTIONS_KEYS.each do |key|
12
+ send("#{key}=", options[key])
13
+ end
14
+ end
15
+
16
+ def request(request_type, &block)
17
+ xml = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
18
+ xml.AdXML {
19
+ xml.Request(:type => request_type) {
20
+ yield(xml) if block_given?
21
+ }
22
+ }
23
+ end
24
+ response = webservice.request :n1, :oas_xml_request, :"xmlns:n1" => "http://api.oas.tfsm.com/" do
25
+ soap.body = {
26
+ "String_1" => account.to_s,
27
+ "String_2" => username.to_s,
28
+ "String_3" => password.to_s,
29
+ "String_4" => xml.to_xml
30
+ }
31
+ end
32
+ response = Hash.from_xml(response.to_hash[:oas_xml_request_response][:result])[:AdXML][:Response]
33
+ verify_errors(request_type, response)
34
+ response
35
+ end
36
+
37
+ private
38
+ def verify_errors(request_type, response)
39
+ return if (e = response[:Exception]).nil? && (e = response[request_type.to_sym][:Exception]).nil?
40
+ error_code = e[:errorCode]
41
+ error_msg = e[:content]
42
+ case error_code
43
+ when 550
44
+ raise Oas::InvalidSite.new(error_msg, error_code)
45
+ when 551
46
+ raise Oas::InvalidPage.new(error_msg, error_code)
47
+ else
48
+ raise Oas::Error.new(error_msg, error_code)
49
+ end
50
+ end
51
+
52
+ def webservice
53
+ @webservice ||= Savon::Client.new(endpoint)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,16 @@
1
+ module Oas
2
+ class Client
3
+ # Defines methods related to oas campaigns
4
+ module Campaign
5
+ def campaign(id)
6
+ request("Campaign") do |xml|
7
+ xml.Campaign(:action => "read") {
8
+ xml.Overview {
9
+ xml.Id id
10
+ }
11
+ }
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ module Oas
2
+ class Client
3
+ # Defines methods related to oas campaign creatives
4
+ module Creative
5
+ def creative(campaign_id, id)
6
+ request("Creative") do |xml|
7
+ xml.Creative(:action => "read") {
8
+ xml.CampaignId campaign_id
9
+ xml.Id id
10
+ }
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,96 @@
1
+ module Oas
2
+ class Client
3
+ # Defines methods related to oas database section
4
+ module Database
5
+ def advertiser(id)
6
+ request("Advertiser") do |xml|
7
+ xml.Database(:action => "read") {
8
+ xml.Advertiser {
9
+ xml.Id id
10
+ }
11
+ }
12
+ end
13
+ end
14
+
15
+ def agency(id)
16
+ request("Agency") do |xml|
17
+ xml.Database(:action => "read") {
18
+ xml.Agency {
19
+ xml.Id id
20
+ }
21
+ }
22
+ end
23
+ end
24
+
25
+ def campaign_group(id)
26
+ request("CampaignGroup") do |xml|
27
+ xml.Database(:action => "read") {
28
+ xml.CampaignGroup {
29
+ xml.Id id
30
+ }
31
+ }
32
+ end
33
+ end
34
+
35
+ def keyname(name)
36
+ request("Keyname") do |xml|
37
+ xml.Database(:action => "read") {
38
+ xml.Keyname {
39
+ xml.Name name
40
+ }
41
+ }
42
+ end
43
+ end
44
+
45
+ def keyword(id)
46
+ request("Keyword") do |xml|
47
+ xml.Database(:action => "read") {
48
+ xml.Keyword {
49
+ xml.Id id
50
+ }
51
+ }
52
+ end
53
+ end
54
+
55
+ def page(url)
56
+ request("Page") do |xml|
57
+ xml.Database(:action => "read") {
58
+ xml.Page {
59
+ xml.Url url
60
+ }
61
+ }
62
+ end
63
+ end
64
+
65
+ def section(id)
66
+ request("Section") do |xml|
67
+ xml.Database(:action => "read") {
68
+ xml.Section {
69
+ xml.Id id
70
+ }
71
+ }
72
+ end
73
+ end
74
+
75
+ def site(id)
76
+ request("Site") do |xml|
77
+ xml.Database(:action => "read") {
78
+ xml.Site {
79
+ xml.Id id
80
+ }
81
+ }
82
+ end
83
+ end
84
+
85
+ def site_group(id)
86
+ request("SiteGroup") do |xml|
87
+ xml.Database(:action => "read") {
88
+ xml.SiteGroup {
89
+ xml.Id id
90
+ }
91
+ }
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,15 @@
1
+ module Oas
2
+ class Client
3
+ # Defines methods related to oas campaigns
4
+ module Notification
5
+ def notification(campaign_id, event_name)
6
+ request("Notification") do |xml|
7
+ xml.Notification(:action => "read") {
8
+ xml.CampaignId campaign_id
9
+ xml.EventName event_name
10
+ }
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ module Oas
2
+ class Client
3
+ module Utils
4
+ private
5
+ def build_attributes(xml, attributes = {})
6
+ attributes.each do |key,value|
7
+ if value.is_a?(Hash)
8
+ build_attributes(xml, value)
9
+ else
10
+ xml.send(key.to_sym, value)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
data/lib/oas/client.rb ADDED
@@ -0,0 +1,15 @@
1
+ module Oas
2
+ class Client < Api
3
+ require 'oas/client/utils'
4
+ require 'oas/client/campaign'
5
+ require 'oas/client/creative'
6
+ require 'oas/client/database'
7
+ require 'oas/client/notification'
8
+
9
+ include Oas::Client::Utils
10
+ include Oas::Client::Campaign
11
+ include Oas::Client::Creative
12
+ include Oas::Client::Database
13
+ include Oas::Client::Notification
14
+ end
15
+ end
@@ -0,0 +1,45 @@
1
+ module Oas
2
+ module Configuration
3
+ # An array of valid keys in the options hash when configuring a {Twitter::Client}
4
+ VALID_OPTIONS_KEYS = [
5
+ :endpoint,
6
+ :account,
7
+ :username,
8
+ :password].freeze
9
+
10
+ # The endpoint that will be used to connect if none is set
11
+ DEFAULT_ENDPOINT = "https://oas.realmedianetwork.net/oasapi/OaxApi?wsdl".freeze
12
+
13
+ # The account that will be used to connect if none is set
14
+ DEFAULT_ACCOUNT = "OasDefault"
15
+
16
+ # By default, don't set a username
17
+ DEFAULT_USERNAME = nil
18
+
19
+ # By default, don't set a password
20
+ DEFAULT_PASSWORD = nil
21
+
22
+ attr_accessor *VALID_OPTIONS_KEYS
23
+
24
+ def self.extended(base)
25
+ base.reset
26
+ end
27
+
28
+ def configure
29
+ yield self if block_given?
30
+ end
31
+
32
+ def options
33
+ options = {}
34
+ VALID_OPTIONS_KEYS.each{|k| options[k] = send(k) }
35
+ options
36
+ end
37
+
38
+ def reset
39
+ self.endpoint = DEFAULT_ENDPOINT
40
+ self.account = DEFAULT_ACCOUNT
41
+ self.username = DEFAULT_USERNAME
42
+ self.password = DEFAULT_PASSWORD
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,57 @@
1
+ require 'nokogiri'
2
+
3
+ class Hash
4
+ class << self
5
+ def from_xml(xml_io)
6
+ result = Nokogiri::XML(xml_io)
7
+ return { result.root.name.to_sym => xml_node_to_hash(result.root) }
8
+ end
9
+
10
+ def xml_node_to_hash(node)
11
+ # If we are at the root of the document, start the hash
12
+ if node.element?
13
+ result_hash = {}
14
+ if node.attributes != {}
15
+ node.attributes.keys.each do |key|
16
+ result_hash[node.attributes[key].name.to_sym] = prepare(node.attributes[key].value)
17
+ end
18
+ end
19
+ if node.children.size > 0
20
+ node.children.each do |child|
21
+ result = xml_node_to_hash(child)
22
+
23
+ if child.name == "text"
24
+ unless child.next_sibling || child.previous_sibling
25
+ result = prepare(result)
26
+ return result if result_hash.empty?
27
+ result_hash[:content] = result
28
+ return result_hash
29
+ end
30
+ elsif result_hash[child.name.to_sym]
31
+ if result_hash[child.name.to_sym].is_a?(Object::Array)
32
+ result_hash[child.name.to_sym] << prepare(result)
33
+ else
34
+ result_hash[child.name.to_sym] = [result_hash[child.name.to_sym]] << prepare(result)
35
+ end
36
+ else
37
+ result_hash[child.name.to_sym] = prepare(result)
38
+ end
39
+ end
40
+ return result_hash
41
+ else
42
+ return nil
43
+ end
44
+ else
45
+ return prepare(node.content.to_s)
46
+ end
47
+ end
48
+
49
+ def prepare(data)
50
+ (data.class == String && data.to_i.to_s == data) ? data.to_i : data
51
+ end
52
+ end
53
+
54
+ def to_struct(struct_name)
55
+ Struct.new(struct_name,*keys).new(*values)
56
+ end
57
+ end
@@ -0,0 +1,6 @@
1
+ class Object
2
+ # From activesupport/lib/active_support/core_ext/object/blank.rb, line 12
3
+ def blank?
4
+ respond_to?(:empty?) ? empty? : !self
5
+ end
6
+ end
data/lib/oas/error.rb ADDED
@@ -0,0 +1,17 @@
1
+ module Oas
2
+ # Custom error class for rescuing from all Oas errors
3
+ class Error < StandardError
4
+ attr_reader :error_code
5
+
6
+ def initialize(message, error_code)
7
+ @error_code = error_code
8
+ super message
9
+ end
10
+ end
11
+
12
+ # Raised when Oas returns the error code 550
13
+ class InvalidSite < Error; end
14
+
15
+ # Raised when Oas returns the error code 551
16
+ class InvalidUrl < Error; end
17
+ end
@@ -0,0 +1,3 @@
1
+ module Oas
2
+ VERSION = "0.1.0"
3
+ end
data/lib/oas.rb ADDED
@@ -0,0 +1,31 @@
1
+ Dir[File.join(File.dirname(__FILE__),'oas/core_ext/**/*.rb')].each {|f| require f}
2
+
3
+ require 'oas/version'
4
+ require 'oas/error'
5
+ require 'oas/configuration'
6
+ require 'oas/api'
7
+ require 'oas/client'
8
+
9
+ module Oas
10
+ extend Configuration
11
+
12
+ # Alias for Oas::Client.new
13
+ #
14
+ # @return [Oas::Client]
15
+ def self.client(options={})
16
+ Oas::Client.new(options)
17
+ end
18
+
19
+ # Delegate to Oas::Client
20
+ def self.method_missing(method, *args, &block)
21
+ return super unless client.respond_to?(method)
22
+ client.send(method, *args, &block)
23
+ end
24
+
25
+ def self.respond_to?(method, include_private = false)
26
+ client.respond_to?(method, include_private) || super(method, include_private)
27
+ end
28
+
29
+ HTTPI.log = false
30
+ Savon.configure { |c| c.log = false }
31
+ end
data/oas.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "oas/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "oas"
7
+ s.version = Oas::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Damian Caruso"]
10
+ s.email = ["damian.caruso@gmail.com"]
11
+ s.homepage = "http://github.com/realmedia/ruby-oas"
12
+ s.summary = %q{Ruby wrapper for the OAS 7.4 API}
13
+ s.description = %q{Ruby wrapper for the OAS 7.4 API}
14
+
15
+ s.rubyforge_project = "oas"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_dependency "httpclient", "~> 2.2.0.2"
23
+ s.add_dependency "nokogiri", "~> 1.4.4"
24
+ s.add_dependency "savon", "~> 0.9.2"
25
+
26
+ s.add_development_dependency "rspec", "~> 2.5.0"
27
+ s.add_development_dependency "webmock", "~> 1.6.2"
28
+ end
@@ -0,0 +1,49 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
3
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
4
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
5
+ <soapenv:Body>
6
+ <ns1:OasXmlRequestResponse xmlns:ns1="http://api.oas.tfsm.com/">
7
+ <result>
8
+ <![CDATA[
9
+ <?xml version="1.0"?>
10
+ <AdXML>
11
+ <Response>
12
+ <Advertiser>
13
+ <Id>advertiser_id</Id>
14
+ <Organization>A Company Name</Organization>
15
+ <Notes></Notes>
16
+ <ContactFirstName></ContactFirstName>
17
+ <ContactLastName></ContactLastName>
18
+ <ContactTitle></ContactTitle>
19
+ <Email></Email>
20
+ <Phone></Phone>
21
+ <Fax></Fax>
22
+ <ExternalUsers/>
23
+ <BillingInformation>
24
+ <Method>
25
+ <Code>O</Code>
26
+ </Method>
27
+ <Address>test address2</Address>
28
+ <City>Philadelphia</City>
29
+ <State>
30
+ <Code>US:PA</Code>
31
+ </State>
32
+ <Country>
33
+ <Code>US</Code>
34
+ </Country>
35
+ <Zip>20007</Zip>
36
+ <Email>testmail@247realmeida.com</Email>
37
+ </BillingInformation>
38
+ <WhoCreated>realmedia</WhoCreated>
39
+ <WhenCreated>01/20/2008 20:59:29</WhenCreated>
40
+ <WhoModified>realmedia</WhoModified>
41
+ <WhenModified>01/20/2008 21:22:33</WhenModified>
42
+ </Advertiser>
43
+ </Response>
44
+ </AdXML>
45
+ ]]>
46
+ </result>
47
+ </ns1:OasXmlRequestResponse>
48
+ </soapenv:Body>
49
+ </soapenv:Envelope>
@@ -0,0 +1,49 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
3
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
4
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
5
+ <soapenv:Body>
6
+ <ns1:OasXmlRequestResponse xmlns:ns1="http://api.oas.tfsm.com/">
7
+ <result>
8
+ <![CDATA[
9
+ <?xml version="1.0"?>
10
+ <AdXML>
11
+ <Response>
12
+ <Agency>
13
+ <Id>agency_id</Id>
14
+ <Organization>A Company Name</Organization>
15
+ <Notes>This Agency was added through the API.(With Billing Info)</Notes>
16
+ <ContactFirstName>Nobody</ContactFirstName>
17
+ <ContactLastName>Kim</ContactLastName>
18
+ <ContactTitle>Senior Engineer</ContactTitle>
19
+ <Email>nobody@247realmedia.com</Email>
20
+ <Phone>123-123-1234</Phone>
21
+ <Fax>123-123-1235</Fax>
22
+ <ExternalUsers>
23
+ <UserId>ExtUser1</UserId>
24
+ <UserId>ExtUser2</UserId>
25
+ </ExternalUsers>
26
+ <BillingInformation>
27
+ <Method>
28
+ <Code>M</Code>
29
+ </Method>
30
+ <Address>51-12 BANPO 4-DONG SEOCHO-GU, SEOUL, SOUTH KOREA</Address>
31
+ <City>SEOUL</City>
32
+ <State>
33
+ <Code>KR:SOULTUKPYOLS</Code>
34
+ </State>
35
+ <Country>
36
+ <Code>KR</Code>
37
+ </Country>
38
+ <Zip>137-802</Zip>
39
+ </BillingInformation>
40
+ <InternalQuickReport>short</InternalQuickReport>
41
+ <ExternalQuickReport>to-date</ExternalQuickReport>
42
+ </Agency>
43
+ </Response>
44
+ </AdXML>
45
+ ]]>
46
+ </result>
47
+ </ns1:OasXmlRequestResponse>
48
+ </soapenv:Body>
49
+ </soapenv:Envelope>