jjp-openx 1.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ *.swp
2
+ .svn/
3
+ pkg/
data/History.txt ADDED
@@ -0,0 +1,24 @@
1
+ === 1.0.0 / 2008-04-07
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
6
+
7
+ === 1.1.0 / 2009-10-26
8
+
9
+ * 2 major enhancements
10
+
11
+ * OpenX API Version 2 Support added
12
+ * OpenX Invocation API Support added
13
+
14
+ * 1 minor enhancement
15
+
16
+ * Ruby on Rails documentation support added
17
+
18
+ === 1.1.1 / 2009-11-06
19
+
20
+ * Minor bugfix to environment handling for Win32 users
21
+
22
+ === 1.1.2 / 2009-11-19
23
+
24
+ * Documentation updates and patch to enable banner support on the OpenX Server
data/Manifest.txt ADDED
@@ -0,0 +1,26 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ lib/openx.rb
6
+ lib/openx/image.rb
7
+ lib/openx/services.rb
8
+ lib/openx/services/advertiser.rb
9
+ lib/openx/services/agency.rb
10
+ lib/openx/services/banner.rb
11
+ lib/openx/services/base.rb
12
+ lib/openx/services/campaign.rb
13
+ lib/openx/services/publisher.rb
14
+ lib/openx/services/session.rb
15
+ lib/openx/services/zone.rb
16
+ test/assets/300x250.jpg
17
+ test/assets/cat.swf
18
+ test/helper.rb
19
+ test/test_advertiser.rb
20
+ test/test_agency.rb
21
+ test/test_banner.rb
22
+ test/test_base.rb
23
+ test/test_campaign.rb
24
+ test/test_publisher.rb
25
+ test/test_session.rb
26
+ test/test_zone.rb
data/README.rdoc ADDED
@@ -0,0 +1,139 @@
1
+ = OpenX
2
+
3
+ * http://rubygems.org/gems/jjp-openx
4
+ * http://github.com/DoppioJP/openx
5
+
6
+ == Description
7
+
8
+ A Ruby interface to the OpenX XML-RPC API. Used touchlocal 1.1.2 version as base for adding more API calls to OpenX API from http://developer.openx.org/api/
9
+
10
+ == Synopsis
11
+
12
+ OpenX::Services::Base.configuration = {
13
+ 'username' => 'admin',
14
+ 'password' => 'password',
15
+ 'url' => 'http://localhost/www/api/v2/xmlrpc/',
16
+ }
17
+
18
+ OpenX::Services::Agency.find(:all).each do |agency|
19
+ puts agency.name
20
+
21
+ # Look up publishers
22
+ agency.publishers.each do |publisher|
23
+ puts "-- #{publisher.name}"
24
+ end
25
+
26
+ # Create a publisher
27
+ Publisher.create!(
28
+ :agency => agency,
29
+ :name => 'My Test Publisher',
30
+ :contact_name => 'My Contact',
31
+ :email => 'agency@example.com',
32
+ :username => 'user',
33
+ :password => 'password'
34
+ )
35
+ end
36
+
37
+ == Requirements
38
+
39
+ * ruby
40
+
41
+ == Install
42
+
43
+ * sudo gem install touchlocal-openx --source "http://gemcutter.org"
44
+ * add "require 'openx'" to your code
45
+ * Update your $HOME/.openx/credentials.yml file. Here is a sample:
46
+
47
+ production:
48
+ username: admin
49
+ password: admin
50
+ url: http://www.example.com/www/api/v2/xmlrpc/
51
+ invocation_url: http://www.example.com/www/delivery/axmlrpc.php
52
+
53
+ The YAML file lists configuration for each environment. The gem uses the
54
+ 'production' environment by default. Trailing slash is required on the 'url'.
55
+ 'invocation_url' is only used by the OpenX::Invocation methods to serve
56
+ advertisements over XML-RPC
57
+
58
+ == Ruby on Rails Integration
59
+
60
+ As common deployment scenarios for RoR projects dictates that you manage all
61
+ of your dependent files from within your project, storing your credentials.yml
62
+ file in the default location (as above) will not work. However, this is easily
63
+ fixed.
64
+
65
+ Create your credentials.yml file in your ./config folder, and populate it with
66
+ the necessary environment settings. It may in fact be more useful to name your
67
+ file something like openx_credentials.yml to be explicit about the content.
68
+
69
+ Then, add your gem require line to the initialize block of the environment.rb:
70
+
71
+ config.gem "touchlocal-openx",
72
+ :lib => "openx", :source => "http://gemcutter.org"
73
+
74
+ You will of course need to install the gem, either manually or via
75
+ rake gems:install
76
+
77
+ Finally, create a config/initializers/openx.rb and include the following:
78
+
79
+ require 'yaml'
80
+ OpenX::Services::Base.configuration =
81
+ YAML.load_file(File.join(Rails.root, 'config', 'credentials.yml'))[Rails.env]
82
+
83
+
84
+ == Banner Keyword Support
85
+
86
+ Not all attributes of OpenX objects that can be set in the web interface are
87
+ accessible via the API. A notable case of this is the ability to access
88
+ Banner Keywords. While it seems to be a case of "We'll add them as people
89
+ need them," this process is slower than one might expect;
90
+ https://developer.openx.org/jira/browse/OX-4779 has been an open ticket since
91
+ January 2009.
92
+
93
+ As TouchLocal required the ability to access Banner Keywords, the
94
+ OpenX::Services::Banner object has the support for this attribute. If the
95
+ server does not support the attribute, then setting it will have no effect,
96
+ and it will return nil when retrieving it. To enable support on the server,
97
+ you will need access to the server source, and the included
98
+ php/openx-2.8.1-keywords.diff
99
+
100
+ Copy the openx-2.8.1-keywords.diff file to the root of the OpenX distribution
101
+ on your server, and execute:
102
+
103
+ patch -p0 < openx-2.8.1-keywords.diff
104
+
105
+ This will patch the relevant OpenX API to allow access to the keyword
106
+ attribute, meaning that now both your client and server support it. Happy days.
107
+
108
+ This patch has been tested on OpenX Server versions 2.8.1 and 2.8.2 at the
109
+ time of writing.
110
+
111
+
112
+ == License
113
+
114
+ (The MIT License)
115
+
116
+ Copyright (c) 2008:
117
+
118
+ * {Aaron Patterson}[http://tenderlovemaking.com]
119
+ * Andy Smith
120
+ * {TouchLocal Ltd}[http://www.touchlocal.com]
121
+
122
+ Permission is hereby granted, free of charge, to any person obtaining
123
+ a copy of this software and associated documentation files (the
124
+ 'Software'), to deal in the Software without restriction, including
125
+ without limitation the rights to use, copy, modify, merge, publish,
126
+ distribute, sublicense, and/or sell copies of the Software, and to
127
+ permit persons to whom the Software is furnished to do so, subject to
128
+ the following conditions:
129
+
130
+ The above copyright notice and this permission notice shall be
131
+ included in all copies or substantial portions of the Software.
132
+
133
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
134
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
135
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
136
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
137
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
138
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
139
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'rake'
5
+
6
+ begin
7
+ require 'jeweler'
8
+ Jeweler::Tasks.new do |gemspec|
9
+ gemspec.name = "jjp-openx"
10
+ gemspec.summary = "A Ruby interface to the OpenX XML-RPC API with more OpenX APIs used"
11
+ gemspec.description = "A Ruby interface to the OpenX XML-RPC API. Used touchlocal 1.1.2 version as base for adding more API calls to OpenX API from http://developer.openx.org/api/"
12
+ gemspec.email = "jacobjp@mac.com"
13
+ gemspec.homepage = "http://github.com/DoppioJP/openx"
14
+ gemspec.authors = ["Aaron Patterson", "Andy Smith", "TouchLocal Plc", "DoppioJP"]
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
19
+ end
20
+
21
+ $: << "lib/"
22
+ require 'openx'
23
+
24
+ namespace :openx do
25
+ task :clean do
26
+ include OpenX::Services
27
+ ENV['OPENX_ENV'] = 'test'
28
+ Agency.find(:all) do |agency|
29
+ Advertiser.find(:all, agency.id).each do |advertiser|
30
+ Campaign.find(:all, advertiser.id).each do |campaign|
31
+ Banner.find(:all, campaign.id).each do |banner|
32
+ banner.destroy
33
+ end
34
+ campaign.destroy
35
+ end
36
+ advertiser.destroy
37
+ end
38
+ end
39
+ end
40
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.1.4
data/jjp-openx.gemspec ADDED
@@ -0,0 +1,78 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{jjp-openx}
8
+ s.version = "1.1.4"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Aaron Patterson", "Andy Smith", "TouchLocal Plc", "DoppioJP"]
12
+ s.date = %q{2010-04-18}
13
+ s.description = %q{A Ruby interface to the OpenX XML-RPC API. Used touchlocal 1.1.2 version as base for adding more API calls to OpenX API from http://developer.openx.org/api/}
14
+ s.email = %q{jacobjp@mac.com}
15
+ s.extra_rdoc_files = [
16
+ "README.rdoc"
17
+ ]
18
+ s.files = [
19
+ ".gitignore",
20
+ "History.txt",
21
+ "Manifest.txt",
22
+ "README.rdoc",
23
+ "Rakefile",
24
+ "VERSION",
25
+ "jjp-openx.gemspec",
26
+ "lib/openx.rb",
27
+ "lib/openx/image.rb",
28
+ "lib/openx/invocation.rb",
29
+ "lib/openx/services.rb",
30
+ "lib/openx/services/advertiser.rb",
31
+ "lib/openx/services/agency.rb",
32
+ "lib/openx/services/banner.rb",
33
+ "lib/openx/services/base.rb",
34
+ "lib/openx/services/campaign.rb",
35
+ "lib/openx/services/publisher.rb",
36
+ "lib/openx/services/session.rb",
37
+ "lib/openx/services/zone.rb",
38
+ "lib/openx/xmlrpc_client.rb",
39
+ "php/openx-2.8.1-keywords.diff",
40
+ "test/assets/300x250.jpg",
41
+ "test/assets/cat.swf",
42
+ "test/helper.rb",
43
+ "test/test_advertiser.rb",
44
+ "test/test_agency.rb",
45
+ "test/test_banner.rb",
46
+ "test/test_base.rb",
47
+ "test/test_campaign.rb",
48
+ "test/test_publisher.rb",
49
+ "test/test_session.rb",
50
+ "test/test_zone.rb"
51
+ ]
52
+ s.homepage = %q{http://github.com/DoppioJP/openx}
53
+ s.rdoc_options = ["--charset=UTF-8"]
54
+ s.require_paths = ["lib"]
55
+ s.rubygems_version = %q{1.3.6}
56
+ s.summary = %q{A Ruby interface to the OpenX XML-RPC API with more OpenX APIs used}
57
+ s.test_files = [
58
+ "test/helper.rb",
59
+ "test/test_advertiser.rb",
60
+ "test/test_agency.rb",
61
+ "test/test_banner.rb",
62
+ "test/test_base.rb",
63
+ "test/test_campaign.rb",
64
+ "test/test_publisher.rb",
65
+ "test/test_session.rb",
66
+ "test/test_zone.rb"
67
+ ]
68
+
69
+ if s.respond_to? :specification_version then
70
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
71
+ s.specification_version = 3
72
+
73
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
74
+ else
75
+ end
76
+ else
77
+ end
78
+ end
@@ -0,0 +1,22 @@
1
+ module OpenX
2
+ class Image
3
+ include XMLRPC::Marshallable
4
+ attr_accessor :filename, :content, :editswf
5
+
6
+ def initialize(hash_or_file)
7
+ @editswf = 0
8
+ if hash_or_file.is_a?(File)
9
+ @filename = File.basename(hash_or_file.path)
10
+ @editswf = File.basename(@filename, '.swf') == @filename ? 0 : 1
11
+ @content = XMLRPC::Base64.new(hash_or_file.read)
12
+ else
13
+ raise ArgumentError unless hash_or_file.key?(:filename)
14
+ raise ArgumentError unless hash_or_file.key?(:content)
15
+ hash_or_file.each { |k,v| send(:"#{k}=", v) }
16
+ unless self.content.is_a?(XMLRPC::Base64)
17
+ self.content = XMLRPC::Base64.new(self.content)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,64 @@
1
+ module OpenX
2
+ class Invocation
3
+ class << self
4
+ #
5
+ # banner = OpenX::Invocation.view("Plumber")
6
+ #
7
+ # banners = OpenX::Invocation.view("Plumber", :count => 2, :exclude_by_campaignid => true) ;nil
8
+ # banners.each do |banner|
9
+ # puts "Banner #{banner['bannerid']}"
10
+ # end; nil
11
+ #
12
+ def view(what, params = {})
13
+ defaults = {
14
+ :count => 1,
15
+ :campaignid => 0,
16
+ :target => '',
17
+ :source => '',
18
+ :with_text => false,
19
+ :exclusions => [],
20
+ :inclusions => [],
21
+ :exclude_by_campaignid => false,
22
+ :exclude_by_bannerid => false
23
+ }
24
+ params = defaults.merge(params)
25
+
26
+ url = OpenX::Services::Base.configuration['invocation_url']
27
+
28
+ # Basic requirement as per /lib/max/Delivery/XML-RPC.php in OpenX
29
+ settings = {:cookies => [], :remote_addr => 'localhost'}
30
+
31
+ context = [] # used by reference after initial use
32
+ params[:exclusions].each { |item| context << convert_to_context(false, item) }
33
+ params[:inclusions].each { |item| context << convert_to_context(true, item) }
34
+ count = params[:count].to_i
35
+
36
+ remote_params = [ what, params[:campaignid], params[:target], params[:source], params[:with_text], context]
37
+ server = XmlrpcClient.new2(url)
38
+
39
+ out = []
40
+ if count > 0
41
+ (0...count).each do
42
+ out << banner = server.call('openads.view', settings, *remote_params)
43
+ if count > 1
44
+ if params[:exclude_by_campaignid]
45
+ campaign_id = banner['campaignid']
46
+ context << convert_to_context(false, "campaignid:#{campaign_id}")
47
+ elsif params[:exclude_by_bannerid]
48
+ banner_id = banner['bannerid']
49
+ context << convert_to_context(false, "bannerid:#{banner_id}")
50
+ end
51
+ end
52
+ end
53
+ end
54
+ count > 1 ? out : out.first
55
+ end
56
+
57
+ def convert_to_context(is_inclusion, item)
58
+ key = is_inclusion ? '==' : '!='
59
+ { key => item }
60
+ end
61
+ protected :convert_to_context
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,31 @@
1
+ module OpenX
2
+ module Services
3
+ class Advertiser < Base
4
+ openx_accessor :name => :advertiserName,
5
+ :contact_name => :contactName,
6
+ :email => :emailAddress,
7
+ :username => :username,
8
+ :password => :password,
9
+ :agency_id => :agencyId,
10
+ :id => :advertiserId
11
+
12
+ has_one :agency
13
+
14
+ self.create = 'ox.addAdvertiser'
15
+ self.update = 'ox.modifyAdvertiser'
16
+ self.delete = 'ox.deleteAdvertiser'
17
+ self.find_one = 'ox.getAdvertiser'
18
+ self.find_all = 'ox.getAdvertiserListByAgencyId'
19
+
20
+ def initialize(params = {})
21
+ raise "need agency" unless params[:agency_id] || params[:agency]
22
+ params[:agency_id] ||= params[:agency].id
23
+ super(params)
24
+ end
25
+
26
+ def campaigns
27
+ Campaign.find(:all, self.id)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,34 @@
1
+ module OpenX
2
+ module Services
3
+ class Agency < Base
4
+ # Translate our property names to OpenX property names
5
+ openx_accessor :name => :agencyName,
6
+ :contact_name => :contactName,
7
+ :email => :emailAddress,
8
+ :username => :username,
9
+ :password => :password,
10
+ :id => :agencyId,
11
+ :account_id => :accountId
12
+
13
+ self.create = 'ox.addAgency'
14
+ self.update = 'ox.modifyAgency'
15
+ self.delete = 'ox.deleteAgency'
16
+ self.find_one = 'ox.getAgency'
17
+ self.find_all = 'ox.getAgencyList'
18
+
19
+ def create_advertiser!(params = {})
20
+ Advertiser.create!(params.merge({
21
+ :agency => self,
22
+ }))
23
+ end
24
+
25
+ def advertisers
26
+ Advertiser.find(:all, self.id)
27
+ end
28
+
29
+ def publishers
30
+ Publisher.find(:all, self.id)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,119 @@
1
+ require 'date'
2
+
3
+ module OpenX
4
+ module Services
5
+ class Banner < Base
6
+ LOCAL_SQL = 'sql'
7
+ LOCAL_WEB = 'web'
8
+ EXTERNAL = 'url'
9
+ HTML = 'html'
10
+ TEXT = 'txt'
11
+
12
+ RUNNING = 0
13
+ PAUSED = 1
14
+
15
+ class << self
16
+ def find(id, *args)
17
+ session = self.connection
18
+ server = XmlrpcClient.new2("#{session.url}")
19
+ if id == :all
20
+ responses = server.call(find_all(), session, *args)
21
+ response = responses.first
22
+ return [] unless response
23
+ responses = [response]
24
+
25
+ ### Annoying.. For some reason OpenX returns a linked list.
26
+ ### Probably a bug....
27
+ while response.key?('aImage')
28
+ response = response.delete('aImage')
29
+ break unless response
30
+ responses << response
31
+ end
32
+
33
+ responses.map { |response|
34
+ new(translate(response))
35
+ }
36
+ else
37
+ response = server.call(find_one(), session, id)
38
+ new(translate(response))
39
+ end
40
+ end
41
+ end
42
+
43
+ # Translate our property names to OpenX property names
44
+ openx_accessor :name => :bannerName,
45
+ :campaign_id => :campaignId,
46
+ :id => :bannerId,
47
+ :storage_type => :storageType,
48
+ :file_name => :fileName,
49
+ :image_url => :imageURL,
50
+ :html_template => :htmlTemplate,
51
+ :width => :width,
52
+ :height => :height,
53
+ :weight => :weight,
54
+ :target => :target,
55
+ :url => :url,
56
+ :status => :status,
57
+ :adserver => :adserver,
58
+ :transparent => :transparent,
59
+ :image => :aImage,
60
+ :backup_image => :aBackupImage,
61
+ # 'keyword' only supported by patched server
62
+ # as per README.rdoc
63
+ # No averse effect when unsupported by server (returns nil)
64
+ :keyword => :keyword
65
+
66
+ has_one :campaign
67
+
68
+ self.create = 'ox.addBanner'
69
+ self.update = 'ox.modifyBanner'
70
+ self.delete = 'ox.deleteBanner'
71
+ self.find_one = 'ox.getBanner'
72
+ self.find_all = 'ox.getBannerListByCampaignId'
73
+
74
+ def initialize(params = {})
75
+ raise ArgumentError.new("Missing campaign_id") unless params[:campaign_id] || params[:campaign]
76
+ params[:campaign_id] ||= params[:campaign].id
77
+ super(params)
78
+ end
79
+
80
+ # Alias for daily_statistics method to keep consistency with OpenX API calls
81
+ # Originally it was call for ox.bannerDailyStatistics so it is kept for compatibility with the previous version
82
+ def statistics start_on = Date.today, end_on = Date.today
83
+ daily_statistics start_on, end_on
84
+ end
85
+
86
+ # Returns statistics in Array of Hashes by day, which are: impressions, clicks, requests and revenue.
87
+ # Each day is represented by XMLRPC::DateTime which has instant variables:
88
+ # @year, @month, @day, @hour, @min, @sec
89
+ def daily_statistics start_on = Date.today, end_on = Date.today
90
+ session = self.class.connection
91
+ @server.call('ox.bannerDailyStatistics', session, self.id, start_on, end_on)
92
+ end
93
+
94
+ # Returns statistics in Array of Hashes by publisher, which are: impression, clicks, requests and revenue.
95
+ # Also returns publisherName and publisherId
96
+ def publisher_statistics start_on = Date.today, end_on = Date.today
97
+ session = self.class.connection
98
+ @server.call('ox.bannerPublisherStatistics', session, self.id, start_on, end_on)
99
+ end
100
+
101
+ # Returns statistics in Array of Hashes by zone, which are: impression, clicks, requests, conversions and revenue.
102
+ # Also returns publisherName, publisherId, zoneName, zoneId
103
+ def zone_statistics start_on = Date.today, end_on = Date.today
104
+ session = self.class.connection
105
+ @server.call('ox.bannerZoneStatistics', session, self.id, start_on, end_on)
106
+ end
107
+
108
+ def targeting
109
+ session = self.class.connection
110
+ @server.call('ox.getBannerTargeting', session, self.id)
111
+ end
112
+
113
+ def targeting= targeting
114
+ session = self.class.connection
115
+ @server.call('ox.setBannerTargeting', session, self.id, targeting)
116
+ end
117
+ end
118
+ end
119
+ end