touchlocal-openx 1.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,3 @@
1
+ *.swp
2
+ .svn/
3
+ pkg/
data/History.txt ADDED
@@ -0,0 +1,6 @@
1
+ === 1.0.0 / 2008-04-07
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
6
+
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.txt ADDED
@@ -0,0 +1,109 @@
1
+ = openx
2
+
3
+ * http://openx.rubyforge.org
4
+
5
+ == DESCRIPTION:
6
+
7
+ A Ruby interface to the OpenX XML-RPC API.
8
+
9
+ == SYNOPSIS:
10
+
11
+ OpenX::Services::Base.configuration = {
12
+ 'username' => 'admin',
13
+ 'password' => 'password',
14
+ 'url' => 'http://localhost/www/api/v2/xmlrpc/',
15
+ }
16
+
17
+ OpenX::Services::Agency.find(:all).each do |agency|
18
+ puts agency.name
19
+
20
+ # Look up publishers
21
+ agency.publishers.each do |publisher|
22
+ puts "-- #{publisher.name}"
23
+ end
24
+
25
+ # Create a publisher
26
+ Publisher.create!(
27
+ :agency => agency,
28
+ :name => 'My Test Publisher',
29
+ :contact_name => 'Aaron Patterson',
30
+ :email => 'aaron@tenderlovemaking.com',
31
+ :username => 'user',
32
+ :password => 'password'
33
+ )
34
+ end
35
+
36
+ == REQUIREMENTS:
37
+
38
+ * ruby
39
+
40
+ == INSTALL:
41
+
42
+ * sudo gem install openx
43
+ * Update your $HOME/.openx/credentials.yml file. Here is a sample:
44
+
45
+ ---
46
+ production:
47
+ username: admin
48
+ password: admin
49
+ url: http://www.example.com/www/api/v2/xmlrpc/
50
+ invocation_url: http://www.example.com/www/delivery/axmlrpc.php
51
+
52
+ The YAML file lists configuration for each environment. The gem uses the
53
+ 'production' environment by default. Trailing slash is required on the 'url'.
54
+ 'invocation_url' is only used by the OpenX::Invocation methods to serve
55
+ advertisements over XML-RPC
56
+
57
+ == RUBY ON RAILS INTEGRATION
58
+
59
+ As common deployment scenarios for RoR projects dictates that you manage all
60
+ of your dependent files from within your project, storing your credentials.yml
61
+ file in the default location (as above) will not work. However, this is easily
62
+ fixed.
63
+
64
+ Create your credentials.yml file in your ./config folder, and populate it with
65
+ the necessary environment settings. It may in fact be more useful to name your
66
+ file something like openx_credentials.yml to be explicit about the content.
67
+
68
+ Then, add your gem require line to the initialize block of the environment.rb:
69
+
70
+ config.gem "touchlocal-openx",
71
+ :lib => "openx", :source => "http://gemcutter.org"
72
+
73
+ You will of course need to install the gem, either manually or via
74
+ rake gems:install
75
+
76
+ Finally, create a config/initializers/openx.rb and include the following line:
77
+
78
+ OpenX::Services::Base.configuration =
79
+ YAML.load_file(File.join(Rails.root, 'config', 'credentials.yml'))[Rails.env]
80
+
81
+
82
+ == LICENSE:
83
+
84
+ (The MIT License)
85
+
86
+ Copyright (c) 2008:
87
+
88
+ * {Aaron Patterson}[http://tenderlovemaking.com]
89
+ * Andy Smith
90
+ * {TouchLocal Plc}[http://www.touchlocal.com]
91
+
92
+ Permission is hereby granted, free of charge, to any person obtaining
93
+ a copy of this software and associated documentation files (the
94
+ 'Software'), to deal in the Software without restriction, including
95
+ without limitation the rights to use, copy, modify, merge, publish,
96
+ distribute, sublicense, and/or sell copies of the Software, and to
97
+ permit persons to whom the Software is furnished to do so, subject to
98
+ the following conditions:
99
+
100
+ The above copyright notice and this permission notice shall be
101
+ included in all copies or substantial portions of the Software.
102
+
103
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
104
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
105
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
106
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
107
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
108
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
109
+ 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 = "touchlocal-openx"
10
+ gemspec.summary = "A Ruby interface to the OpenX XML-RPC API"
11
+ gemspec.description = "A Ruby interface to the OpenX XML-RPC API"
12
+ gemspec.email = "info@touchlocal.com"
13
+ gemspec.homepage = "http://github.com/touchlocal/openx"
14
+ gemspec.authors = ["Aaron Patterson", "Andy Smith", "TouchLocal Plc"]
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.0
data/lib/openx.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'xmlrpc/client'
2
+ require 'openx/xmlrpc_client'
3
+ require 'openx/services'
4
+ require 'openx/invocation'
5
+ require 'openx/image'
6
+
7
+ module OpenX
8
+ VERSION = '1.1.0'
9
+ 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,63 @@
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
+ settings = {:cookies => [], :remote_addr => 'localhost'}
29
+
30
+ context = [] # used by reference after initial use
31
+ params[:exclusions].each { |item| context << convert_to_context(false, item) }
32
+ params[:inclusions].each { |item| context << convert_to_context(true, item) }
33
+ count = params[:count].to_i
34
+
35
+ remote_params = [ what, params[:campaignid], params[:target], params[:source], params[:with_text], context]
36
+ server = XmlrpcClient.new2(url)
37
+
38
+ out = []
39
+ if count > 0
40
+ (0...count).each do
41
+ out << banner = server.call('openads.view', settings, *remote_params)
42
+ if count > 1
43
+ if params[:exclude_by_campaignid]
44
+ campaign_id = banner['campaignid']
45
+ context << convert_to_context(false, "campaignid:#{campaign_id}")
46
+ elsif params[:exclude_by_bannerid]
47
+ banner_id = banner['bannerid']
48
+ context << convert_to_context(false, "bannerid:#{banner_id}")
49
+ end
50
+ end
51
+ end
52
+ end
53
+ count > 1 ? out : out.first
54
+ end
55
+
56
+ def convert_to_context(is_inclusion, item)
57
+ key = is_inclusion ? '==' : '!='
58
+ { key => item }
59
+ end
60
+ protected :convert_to_context
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,8 @@
1
+ require 'openx/services/base'
2
+ require 'openx/services/session'
3
+ require 'openx/services/advertiser'
4
+ require 'openx/services/agency'
5
+ require 'openx/services/campaign'
6
+ require 'openx/services/banner'
7
+ require 'openx/services/publisher'
8
+ require 'openx/services/zone'
@@ -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,96 @@
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 https://developer.openx.org/jira/browse/OX-4779
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
+ def statistics start_on = Date.today, end_on = Date.today
81
+ session = self.class.connection
82
+ @server.call('ox.bannerDailyStatistics', session, self.id, start_on, end_on)
83
+ end
84
+
85
+ def targeting
86
+ session = self.class.connection
87
+ @server.call('ox.getBannerTargeting', session, self.id)
88
+ end
89
+
90
+ def targeting= targeting
91
+ session = self.class.connection
92
+ @server.call('ox.setBannerTargeting', session, self.id, targeting)
93
+ end
94
+ end
95
+ end
96
+ end