jjp-openx 1.1.4

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