krakatoa-openx 1.9.4
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +8 -0
- data/Gemfile.lock +25 -0
- data/README.txt +85 -0
- data/Rakefile +51 -0
- data/VERSION +1 -0
- data/krakatoa-openx.gemspec +75 -0
- data/lib/openx.rb +44 -0
- data/lib/openx/image.rb +22 -0
- data/lib/openx/invocation.rb +62 -0
- data/lib/openx/persistance.rb +63 -0
- data/lib/openx/services.rb +29 -0
- data/lib/openx/services/advertiser.rb +31 -0
- data/lib/openx/services/agency.rb +38 -0
- data/lib/openx/services/banner.rb +96 -0
- data/lib/openx/services/base.rb +97 -0
- data/lib/openx/services/campaign.rb +56 -0
- data/lib/openx/services/channel.rb +42 -0
- data/lib/openx/services/publisher.rb +36 -0
- data/lib/openx/services/session.rb +44 -0
- data/lib/openx/services/zone.rb +82 -0
- data/lib/openx/targeting_rule.rb +121 -0
- data/lib/openx/targeting_rules.rb +24 -0
- data/lib/openx/xmlrpc_client.rb +75 -0
- data/test/assets/300x250.jpg +0 -0
- data/test/assets/cat.swf +0 -0
- data/test/helper.rb +131 -0
- data/test/test_advertiser.rb +82 -0
- data/test/test_agency.rb +94 -0
- data/test/test_banner.rb +85 -0
- data/test/test_base.rb +40 -0
- data/test/test_campaign.rb +64 -0
- data/test/test_channel.rb +65 -0
- data/test/test_openx.rb +17 -0
- data/test/test_publisher.rb +69 -0
- data/test/test_services.rb +16 -0
- data/test/test_session.rb +42 -0
- data/test/test_targeting_rule.rb +85 -0
- data/test/test_targeting_rules.rb +13 -0
- data/test/test_xmlrpc_client.rb +37 -0
- data/test/test_xmlrpc_session_client.rb +36 -0
- data/test/test_zone.rb +101 -0
- metadata +89 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module OpenX
|
4
|
+
module Services
|
5
|
+
autoload :Base, 'openx/services/base'
|
6
|
+
autoload :Session, 'openx/services/session'
|
7
|
+
autoload :Advertiser, 'openx/services/advertiser'
|
8
|
+
autoload :Agency, 'openx/services/agency'
|
9
|
+
autoload :Campaign, 'openx/services/campaign'
|
10
|
+
autoload :Banner, 'openx/services/banner'
|
11
|
+
autoload :Publisher, 'openx/services/publisher'
|
12
|
+
autoload :Zone, 'openx/services/zone'
|
13
|
+
autoload :Channel, 'openx/services/channel'
|
14
|
+
|
15
|
+
@@connection = nil
|
16
|
+
|
17
|
+
# Default connection
|
18
|
+
def self.default_connection
|
19
|
+
@@connection ||= establish_connection(OpenX.configuration)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.establish_connection(config)
|
23
|
+
connection = Session.new(config['url'])
|
24
|
+
connection.create config['username'], config['password']
|
25
|
+
connection
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
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,38 @@
|
|
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
|
+
|
33
|
+
def statistics(start_on = Date.today, end_on = Date.today)
|
34
|
+
remote.call('ox.agencyBannerStatistics', self.id)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
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
|
+
if id == :all
|
18
|
+
responses = remote.call(find_all, *args)
|
19
|
+
response = responses.first
|
20
|
+
return [] unless response
|
21
|
+
responses = [response]
|
22
|
+
|
23
|
+
### Annoying.. For some reason OpenX returns a linked list.
|
24
|
+
### Probably a bug....
|
25
|
+
while response.key?('aImage')
|
26
|
+
response = response.delete('aImage')
|
27
|
+
break unless response
|
28
|
+
responses << response
|
29
|
+
end
|
30
|
+
|
31
|
+
responses.map do |response|
|
32
|
+
new(translate(response))
|
33
|
+
end
|
34
|
+
else
|
35
|
+
response = remote.call(find_one, id)
|
36
|
+
new(translate(response))
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Translate our property names to OpenX property names
|
42
|
+
openx_accessor :name => :bannerName,
|
43
|
+
:campaign_id => :campaignId,
|
44
|
+
:id => :bannerId,
|
45
|
+
:storage_type => :storageType,
|
46
|
+
:file_name => :fileName,
|
47
|
+
:image_url => :imageURL,
|
48
|
+
:html_template => :htmlTemplate,
|
49
|
+
:width => :width,
|
50
|
+
:height => :height,
|
51
|
+
:weight => :weight,
|
52
|
+
:target => :target,
|
53
|
+
:url => :url,
|
54
|
+
:status => :status,
|
55
|
+
:adserver => :adserver,
|
56
|
+
:transparent => :transparent,
|
57
|
+
:image => :aImage,
|
58
|
+
:backup_image => :aBackupImage,
|
59
|
+
# 'keyword' only supported by patched server
|
60
|
+
# as per https://developer.openx.org/jira/browse/OX-4779
|
61
|
+
# No averse effect when unsupported by server (returns nil)
|
62
|
+
:keyword => :keyword,
|
63
|
+
:comments => :comments
|
64
|
+
|
65
|
+
has_one :campaign
|
66
|
+
|
67
|
+
self.create = 'ox.addBanner'
|
68
|
+
self.update = 'ox.modifyBanner'
|
69
|
+
self.delete = 'ox.deleteBanner'
|
70
|
+
self.find_one = 'ox.getBanner'
|
71
|
+
self.find_all = 'ox.getBannerListByCampaignId'
|
72
|
+
|
73
|
+
def initialize(params = {})
|
74
|
+
raise ArgumentError.new("Missing campaign_id") unless params[:campaign_id] || params[:campaign]
|
75
|
+
params[:campaign_id] ||= params[:campaign].id
|
76
|
+
super(params)
|
77
|
+
end
|
78
|
+
|
79
|
+
def statistics start_on = Date.today, end_on = Date.today
|
80
|
+
remote.call('ox.bannerDailyStatistics', self.id, start_on, end_on)
|
81
|
+
end
|
82
|
+
|
83
|
+
def targeting
|
84
|
+
raise "Banner must be saved" if new_record?
|
85
|
+
remote.call('ox.getBannerTargeting', self.id).map do |line|
|
86
|
+
TargetingRule.instantiate(line)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def targeting=(rules)
|
91
|
+
raise "Banner must be saved" if new_record?
|
92
|
+
remote.call('ox.setBannerTargeting', self.id, rules)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module OpenX
|
2
|
+
module Services
|
3
|
+
class Base
|
4
|
+
extend Persistance::ClassMethods
|
5
|
+
include Persistance::InstanceMethods
|
6
|
+
include Comparable
|
7
|
+
|
8
|
+
class << self
|
9
|
+
attr_accessor :translations
|
10
|
+
attr_writer :connection
|
11
|
+
attr_accessor :create, :update, :delete, :find_one, :find_all
|
12
|
+
|
13
|
+
# Establishes a custom connection. Example:
|
14
|
+
#
|
15
|
+
# class MyBanner < OpenX::Services::Banner
|
16
|
+
# establish_connection 'url' => 'http://custom.host/openx', 'user' => 'admin', 'password' => 'password'
|
17
|
+
# end
|
18
|
+
def establish_connection(conn)
|
19
|
+
conn = OpenX::Services.establish_connection(conn) if conn.is_a?(Hash)
|
20
|
+
self.connection = conn
|
21
|
+
end
|
22
|
+
|
23
|
+
# Execute a block using a custom connection. Example:
|
24
|
+
# custom_conn = OpenX::Services.establish_connection({ ... })
|
25
|
+
#
|
26
|
+
# OpenX::Services::Agency.with_connection(custom_conn) do
|
27
|
+
# OpenX::Services::Agency.find(:all)
|
28
|
+
# end
|
29
|
+
def with_connection(temporary)
|
30
|
+
current = @connection
|
31
|
+
begin
|
32
|
+
establish_connection(temporary)
|
33
|
+
yield
|
34
|
+
ensure
|
35
|
+
establish_connection(current)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns the current connection (session)
|
40
|
+
def connection
|
41
|
+
@connection = nil unless defined?(@connection)
|
42
|
+
@connection || OpenX::Services.default_connection
|
43
|
+
end
|
44
|
+
|
45
|
+
# Remote API proxy. Example:
|
46
|
+
#
|
47
|
+
# OpenX::Services::Agency.remote.call 'ox.addAgency', ...
|
48
|
+
def remote
|
49
|
+
connection.remote
|
50
|
+
end
|
51
|
+
|
52
|
+
def has_one(*things)
|
53
|
+
things.each do |thing|
|
54
|
+
attr_writer :"#{thing}"
|
55
|
+
define_method(:"#{thing}") do
|
56
|
+
klass = thing.to_s.capitalize.gsub(/_[a-z]/) { |m| m[1].chr.upcase }
|
57
|
+
klass = OpenX::Services.const_get(:"#{klass}")
|
58
|
+
klass.find(send("#{thing}_id"))
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def openx_accessor(accessor_map)
|
64
|
+
@translations ||= {}
|
65
|
+
@translations = accessor_map.merge(@translations)
|
66
|
+
accessor_map.each do |ruby,openx|
|
67
|
+
attr_accessor :"#{ruby}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def initialize(params = {})
|
73
|
+
@id = nil
|
74
|
+
params.each { |k,v| send(:"#{k}=", v) }
|
75
|
+
end
|
76
|
+
|
77
|
+
def new_record?
|
78
|
+
@id.nil?
|
79
|
+
end
|
80
|
+
|
81
|
+
def <=>(other)
|
82
|
+
self.id <=> other.id
|
83
|
+
end
|
84
|
+
|
85
|
+
protected
|
86
|
+
|
87
|
+
def connection
|
88
|
+
self.class.connection
|
89
|
+
end
|
90
|
+
|
91
|
+
def remote
|
92
|
+
self.class.remote
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module OpenX
|
2
|
+
module Services
|
3
|
+
class Campaign < Base
|
4
|
+
# Translate our property names to OpenX property names
|
5
|
+
openx_accessor :name => :campaignName,
|
6
|
+
:advertiser_id => :advertiserId,
|
7
|
+
:id => :campaignId,
|
8
|
+
:start_date => :startDate,
|
9
|
+
:end_date => :endDate,
|
10
|
+
:impressions => :impressions,
|
11
|
+
:target_impressions => :targetImpressions,
|
12
|
+
:target_clicks => :targetClicks,
|
13
|
+
:revenue => :revenue,
|
14
|
+
:revenue_type => :revenueType,
|
15
|
+
:impressions => :impressions,
|
16
|
+
:clicks => :clicks,
|
17
|
+
:priority => :priority,
|
18
|
+
:weight => :weight,
|
19
|
+
:campaign_type => :campaignType,
|
20
|
+
:comments => :comments
|
21
|
+
|
22
|
+
has_one :advertiser
|
23
|
+
|
24
|
+
self.create = 'ox.addCampaign'
|
25
|
+
self.update = 'ox.modifyCampaign'
|
26
|
+
self.delete = 'ox.deleteCampaign'
|
27
|
+
self.find_one = 'ox.getCampaign'
|
28
|
+
self.find_all = 'ox.getCampaignListByAdvertiserId'
|
29
|
+
|
30
|
+
# Revenue types
|
31
|
+
CPM = 1
|
32
|
+
CPC = 2
|
33
|
+
CPA = 3
|
34
|
+
MONTHLY_TENANCY = 4
|
35
|
+
|
36
|
+
# Campaign types
|
37
|
+
REMNANT = 1
|
38
|
+
HIGH = 2
|
39
|
+
EXCLUSIVE = 3
|
40
|
+
|
41
|
+
def initialize(params = {})
|
42
|
+
raise ArgumentError.new("Missing advertiser_id") unless params[:advertiser_id] || params[:advertiser]
|
43
|
+
params[:advertiser_id] ||= params[:advertiser].id
|
44
|
+
super(params)
|
45
|
+
end
|
46
|
+
|
47
|
+
def statistics(start_on = Date.today, end_on = Date.today)
|
48
|
+
remote.call('ox.campaignBannerStatistics', self.id, start_on, end_on)
|
49
|
+
end
|
50
|
+
|
51
|
+
def banners
|
52
|
+
Banner.find(:all, self.id)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module OpenX
|
2
|
+
module Services
|
3
|
+
class Channel < Base
|
4
|
+
|
5
|
+
openx_accessor :name => :channelName,
|
6
|
+
:id => :channelId,
|
7
|
+
:comments => :comments,
|
8
|
+
:description => :description,
|
9
|
+
:publisher_id => :websiteId,
|
10
|
+
:agency_id => :agencyId
|
11
|
+
|
12
|
+
has_one :publisher
|
13
|
+
|
14
|
+
self.create = 'ox.addChannel'
|
15
|
+
self.update = 'ox.modifyChannel'
|
16
|
+
self.delete = 'ox.deleteChannel'
|
17
|
+
self.find_one = 'ox.getChannel'
|
18
|
+
self.find_all = 'ox.getChannelListByWebsiteId'
|
19
|
+
|
20
|
+
def initialize(params = {})
|
21
|
+
raise "need publisher" unless params[:publisher_id] || params[:publisher]
|
22
|
+
params[:publisher_id] ||= params[:publisher].id
|
23
|
+
super(params)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Retrieves targeting from channel
|
27
|
+
def targeting
|
28
|
+
raise "Channel must be saved" if new_record?
|
29
|
+
remote.call("ox.getChannelTargeting", self.id).map do |line|
|
30
|
+
TargetingRule.instantiate(line)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Applied targeting to channel. See OpenX::TargetingRules for details
|
35
|
+
def targeting=(rules)
|
36
|
+
raise "Channel must be saved" if new_record?
|
37
|
+
remote.call("ox.setChannelTargeting", self.id, rules)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module OpenX
|
2
|
+
module Services
|
3
|
+
class Publisher < Base
|
4
|
+
openx_accessor :name => :publisherName,
|
5
|
+
:contact_name => :contactName,
|
6
|
+
:email => :emailAddress,
|
7
|
+
:username => :username,
|
8
|
+
:password => :password,
|
9
|
+
:id => :publisherId,
|
10
|
+
:agency_id => :agencyId,
|
11
|
+
:website => :website
|
12
|
+
|
13
|
+
has_one :agency
|
14
|
+
|
15
|
+
self.create = 'ox.addPublisher'
|
16
|
+
self.update = 'ox.modifyPublisher'
|
17
|
+
self.delete = 'ox.deletePublisher'
|
18
|
+
self.find_one = 'ox.getPublisher'
|
19
|
+
self.find_all = 'ox.getPublisherListByAgencyId'
|
20
|
+
|
21
|
+
def initialize(params = {})
|
22
|
+
raise "need agency" unless params[:agency_id] || params[:agency]
|
23
|
+
params[:agency_id] ||= params[:agency].id
|
24
|
+
super(params)
|
25
|
+
end
|
26
|
+
|
27
|
+
def zones
|
28
|
+
Zone.find(:all, self.id)
|
29
|
+
end
|
30
|
+
|
31
|
+
def channels
|
32
|
+
Channel.find(:all, self.id)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module OpenX
|
2
|
+
module Services
|
3
|
+
class Session
|
4
|
+
attr_accessor :id, :uri, :user, :password
|
5
|
+
|
6
|
+
def initialize(url)
|
7
|
+
@uri = URI.parse(url)
|
8
|
+
@client = XmlrpcClient.new(self.url)
|
9
|
+
@id = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def url
|
13
|
+
uri.to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
def host
|
17
|
+
url.sub(/#{Regexp.escape(uri.path)}$/, '')
|
18
|
+
end
|
19
|
+
|
20
|
+
def remote
|
21
|
+
@remote ||= XmlrpcSessionClient.new(self)
|
22
|
+
end
|
23
|
+
|
24
|
+
def create(user, password)
|
25
|
+
self.user = user
|
26
|
+
self.password = password
|
27
|
+
recreate!
|
28
|
+
end
|
29
|
+
|
30
|
+
def recreate!
|
31
|
+
raise "Unable to refresh Session" unless user && password
|
32
|
+
self.id = @client.call('ox.logon', user, password)
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def destroy
|
37
|
+
@client.call('ox.logoff', id)
|
38
|
+
self.id = nil
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|