ppc 1.3.2 → 2.0.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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +21 -339
  3. data/README.md +46 -28
  4. data/Rakefile +1 -0
  5. data/lib/ppc.rb +1 -1
  6. data/lib/ppc/api.rb +18 -14
  7. data/lib/ppc/api/baidu.rb +5 -14
  8. data/lib/ppc/api/baidu/account.rb +28 -23
  9. data/lib/ppc/api/baidu/bulk.rb +1 -1
  10. data/lib/ppc/api/baidu/creative.rb +47 -86
  11. data/lib/ppc/api/baidu/group.rb +43 -74
  12. data/lib/ppc/api/baidu/keyword.rb +73 -166
  13. data/lib/ppc/api/baidu/phone_new_creative.rb +8 -7
  14. data/lib/ppc/api/baidu/plan.rb +51 -34
  15. data/lib/ppc/api/baidu/report.rb +9 -29
  16. data/lib/ppc/api/qihu.rb +7 -111
  17. data/lib/ppc/api/qihu/account.rb +31 -25
  18. data/lib/ppc/api/qihu/bulk.rb +1 -2
  19. data/lib/ppc/api/qihu/creative.rb +57 -74
  20. data/lib/ppc/api/qihu/group.rb +40 -63
  21. data/lib/ppc/api/qihu/keyword.rb +58 -74
  22. data/lib/ppc/api/qihu/plan.rb +52 -32
  23. data/lib/ppc/api/qihu/rank.rb +11 -10
  24. data/lib/ppc/api/qihu/report.rb +41 -94
  25. data/lib/ppc/api/qihu/sublink.rb +44 -41
  26. data/lib/ppc/api/sm.rb +3 -12
  27. data/lib/ppc/api/sm/account.rb +20 -19
  28. data/lib/ppc/api/sm/creative.rb +36 -50
  29. data/lib/ppc/api/sm/group.rb +40 -61
  30. data/lib/ppc/api/sm/keyword.rb +44 -102
  31. data/lib/ppc/api/sm/phone_new_creative.rb +9 -8
  32. data/lib/ppc/api/sm/plan.rb +36 -26
  33. data/lib/ppc/api/sm/report.rb +5 -24
  34. data/lib/ppc/api/sogou.rb +5 -55
  35. data/lib/ppc/api/sogou/account.rb +17 -17
  36. data/lib/ppc/api/sogou/creative.rb +52 -75
  37. data/lib/ppc/api/sogou/group.rb +44 -91
  38. data/lib/ppc/api/sogou/keyword.rb +60 -143
  39. data/lib/ppc/api/sogou/plan.rb +37 -23
  40. data/lib/ppc/api/sogou/report.rb +2 -19
  41. data/lib/ppc/ext.rb +0 -8
  42. data/lib/ppc/operation.rb +60 -83
  43. data/lib/ppc/operation/account.rb +13 -19
  44. data/lib/ppc/operation/creative.rb +0 -20
  45. data/lib/ppc/operation/group.rb +18 -27
  46. data/lib/ppc/operation/keyword.rb +0 -27
  47. data/lib/ppc/operation/plan.rb +34 -22
  48. data/lib/ppc/operation/report.rb +4 -4
  49. data/lib/ppc/operation/sublink.rb +8 -0
  50. data/ppc.gemspec +5 -5
  51. metadata +16 -10
  52. data/lib/ppc/api/shenma.rb +0 -64
  53. data/lib/ppc/api/shenma/report.rb +0 -135
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/lib/ppc.rb CHANGED
@@ -3,7 +3,7 @@ require 'ppc/operation'
3
3
  require 'ppc/ext'
4
4
  module PPC
5
5
 
6
- VERSION = "1.3.2"
6
+ VERSION = "2.0.0"
7
7
 
8
8
  protected
9
9
  def print_debug(var,varname=nil)
@@ -15,6 +15,7 @@ module PPC
15
15
 
16
16
  @map = nil
17
17
  @debug = false
18
+ @match_types = nil
18
19
 
19
20
  def debug_on
20
21
  @debug = true
@@ -87,13 +88,6 @@ module PPC
87
88
  raise 'you need build the response result'
88
89
  end
89
90
 
90
- def is_no_quota(failure, code)
91
- return false if failure.nil?
92
- failure = [failure].flatten
93
- return false if failure.size.zero?
94
- return failure[0]["code"] == code
95
- end
96
-
97
91
  def make_type( params, maps = @map)
98
92
  '''
99
93
  tranfesr ppc api to search engine api
@@ -114,10 +108,9 @@ module PPC
114
108
  @ output:
115
109
  types : list of hash that complying with search engine api
116
110
  '''
117
- params = [ params ] unless params.is_a? Array
118
- params.map do |item|
119
- item.select!{|key| maps.map{|m| m[0]}.include? key}
120
- maps.each{|m| item.filter_and_replace_key(m[1],m[0])}
111
+ [ params ].flatten.map do |item|
112
+ item.select!{|key| maps.any?{|m| m[0] == key} }
113
+ maps.each{|key_new, key_old| item[key_old] = (key_new == :match_type && @match_types ? @match_types[item.delete(key_new)] : item.delete(key_new)) if item[key_new] }
121
114
  item
122
115
  end
123
116
  end
@@ -133,9 +126,20 @@ module PPC
133
126
  @ output:
134
127
  params : list of hash complying with PPC gem api
135
128
  '''
136
- types = [ types ] unless types.is_a? Array
137
- types.map do |item|
138
- maps.each{|m| item.filter_and_replace_key(m[0],m[1])}
129
+ [ types ].flatten.map do |item|
130
+ maps.each{|key_new, key_old|
131
+ value = item.delete(key_old)
132
+ value = item.delete(key_old.to_s) if value.nil?
133
+ next if value.nil?
134
+ if key_new == :pause && (key_old == :status || key_old == :sysStatus)
135
+ if value[/(pause|enable)/]
136
+ value = value[/pause/] ? true : false
137
+ else
138
+ key_new = :status
139
+ end
140
+ end
141
+ item[key_new.to_sym] = (key_new == :match_type && @match_types ? @match_types[value] : value)
142
+ }
139
143
  item
140
144
  end
141
145
  end
@@ -16,7 +16,7 @@ module PPC
16
16
  extend ::PPC::API
17
17
 
18
18
  def self.request_uri(param)
19
- URI("https://api.baidu.com/json/sms/v3/#{param[:service]}Service/#{param[:method]}")
19
+ URI("https://api.baidu.com/json/sms/service/#{param[:service]}Service/#{param[:method]}")
20
20
  end
21
21
 
22
22
  def self.process(response, key, &func)
@@ -33,19 +33,10 @@ module PPC
33
33
  result = {}
34
34
  result[:succ] = response['header']['desc'] =='success'
35
35
  result[:failure] = response['header']['failures']
36
- if !response['body'].nil? && response['body'][key]
37
- result[:result] = func[ response['body'][key] ]
38
- end
39
- result[:no_quota] = is_no_quota(response['header']['failures'], '8501')
40
- return result
41
- end
42
-
43
- def self.reverse_type( types, maps = @map )
44
- types = [ types ] unless types.is_a? Array
45
- types.map do |item|
46
- maps.each{|m| item.filter_and_replace_key(m[0],m[1].to_s)}
47
- item
48
- end
36
+ result[:result] ||= func[ response['body']['data'] ] rescue nil
37
+ result[:rquota] = response['header']['rquota'] if response['header']['rquota']
38
+ result[:no_quota] = (response['header']['failures']['code'] == '8501') rescue true
39
+ result
49
40
  end
50
41
 
51
42
  end # Baidu
@@ -4,28 +4,34 @@ module PPC
4
4
  class Account< Baidu
5
5
  Service = 'Account'
6
6
 
7
- @map = [
8
- [:id,:userid],
9
- [:balance,:balance],
10
- [:cost,:cost],
11
- [:payment,:payment],
12
- [:status,:userStat],
13
- [:budget_type,:budgetType],
14
- [:budget,:budget],
15
- [:region,:regionTarget],
16
- [:exclude_ip,:excludeIp],
17
- [:isdynamic,:isDynamicCreative],
18
- [:dynamic_param,:dynamicCreativeParam],
19
- [:open_domains,:openDomains],
20
- [:reg_domain,:regDomain],
21
- [:offline_time,:budgetOfflineTime],
22
- [:weekly_budget,:weeklyBudget],
23
- [:opt,:opt]
24
- ]
7
+ AccountInfoType = {
8
+ id: :userId,
9
+ balance: :balance,
10
+ pc_balance: :pcBalance,
11
+ mobile_balance: :mobileBalance,
12
+ cost: :cost,
13
+ payment: :payment,
14
+ status: :userStat,
15
+ budget_type: :budgetType,
16
+ budget: :budget,
17
+ region: :regionTarget,
18
+ exclude_ip: :excludeIp,
19
+ isdynamic: :isDynamicCreative,
20
+ isdynamictagsublink: :isDynamicTagSublink,
21
+ isdynamichotredirect: :isDynamicHotRedirect,
22
+ isdynamictitle: :isDynamicTitle,
23
+ dynamic_param: :dynamicCreativeParam,
24
+ open_domains: :openDomains,
25
+ reg_domain: :regDomain,
26
+ offline_time: :budgetOfflineTime,
27
+ weekly_budget: :weeklyBudget,
28
+ }
29
+ @map = AccountInfoType
25
30
 
26
31
  def self.info( auth )
27
- response = request(auth,Service,'getAccountInfo' )
28
- return process( response, 'accountInfoType' ){ |x|reverse_type(x)[0] }
32
+ body = {:accountFields => AccountInfoType.values}
33
+ response = request(auth,Service,'getAccountInfo',body)
34
+ process( response, 'accountInfoType' ){ |x|reverse_type(x)[0] }
29
35
  end
30
36
 
31
37
  def self.update(auth, param = {} )
@@ -35,10 +41,9 @@ module PPC
35
41
  @return : account info_type
36
42
  """
37
43
  # for account service, there is not bulk operation
38
- infoType = make_type( param )[0]
39
- body = { accountInfoType: infoType }
44
+ body = { accountInfo: make_type( param )[0] }
40
45
  response = request(auth,Service,'updateAccountInfo', body)
41
- return process( response, 'accountInfoType' ){ |x|reverse_type(x)[0] }
46
+ process( response, 'accountInfoType' ){ |x|reverse_type(x)[0] }
42
47
  end
43
48
 
44
49
  end
@@ -68,7 +68,7 @@ module PPC
68
68
  rescue => e
69
69
  p "Error encounter:#{e.to_s}"
70
70
  end
71
- return false
71
+ false
72
72
  end
73
73
 
74
74
  end
@@ -5,19 +5,40 @@ module PPC
5
5
  class Creative< Baidu
6
6
  Service = 'Creative'
7
7
 
8
- @map =[
9
- [:id,:creativeId],
10
- [:group_id,:adgroupId],
11
- [:title,:title],
12
- [:description1,:description1],
13
- [:description2,:description2],
14
- [:pc_destination,:pcDestinationUrl],
15
- [:pc_display,:pcDisplayUrl],
16
- [:mobile_destination,:mobileDestinationUrl],
17
- [:mobile_display,:mobileDisplayUrl],
18
- [:pause,:pause],
19
- [:preference,:devicePreference]
20
- ]
8
+ CreativeType = {
9
+ id: :creativeId,
10
+ group_id: :adgroupId,
11
+ title: :title,
12
+ description1: :description1,
13
+ description2: :description2,
14
+ pc_destination: :pcDestinationUrl,
15
+ pc_display: :pcDisplayUrl,
16
+ mobile_destination: :mobileDestinationUrl,
17
+ mobile_display: :mobileDisplayUrl,
18
+ pause: :pause,
19
+ preference: :devicePreference,
20
+ status: :status,
21
+ device_preference: :devicePreference,
22
+ }
23
+ @map = CreativeType
24
+
25
+ def self.info( auth, ids )
26
+ body = { ids: ids, idType: 7, creativeFields: CreativeType.values }
27
+ response = request( auth, Service, 'getCreative', body )
28
+ process(response, 'creativeType' ){|x| reverse_type( x )[0] }
29
+ end
30
+
31
+ def self.all( auth, group_ids )
32
+ body = { ids: group_ids, idType: 5, creativeFields: CreativeType.values}
33
+ response = request( auth, Service, 'getCreative', body )
34
+ process(response, 'groupCreatives' ){|x| reverse_type( x ) }
35
+ end
36
+
37
+ def self.ids( auth, group_ids )
38
+ body = { ids: group_ids, idType: 5, creativeFields: [:creativeId]}
39
+ response = request( auth, Service, 'getCreative', body )
40
+ process(response, 'groupCreativeIds' ){|x| reverse_type( x ) }
41
+ end
21
42
 
22
43
  def self.add( auth, creatives )
23
44
  body = { creativeTypes: make_type( creatives ) }
@@ -25,98 +46,38 @@ module PPC
25
46
  process( response, 'creativeTypes' ){ |x| reverse_type(x) }
26
47
  end
27
48
 
28
- def self.get( auth, ids, getTemp = 0 )
29
- '''
30
- \'getCreativeByCreativeId\'
31
- @ input : creative ids
32
- @ output: creative informations
33
- '''
34
- ids = [ ids ] unless ids.is_a? Array
35
- body = { creativeIds: ids, getTemp: getTemp }
36
- response = request( auth, Service, 'getCreativeByCreativeId', body )
49
+ def self.get( auth, ids )
50
+ body = { ids: ids, idType: 7, creativeFields: CreativeType.values }
51
+ response = request( auth, Service, 'getCreative', body )
37
52
  process( response, 'creativeTypes' ){ |x| reverse_type(x) }
38
53
  end
39
54
 
40
55
  def self.update( auth, creatives )
41
- '''
42
- 根据实际使用情况,更新的时候creative title为必填选
43
- '''
44
56
  body = { creativeTypes: make_type( creatives ) }
45
57
  response = request( auth, Service, 'updateCreative', body )
46
58
  process( response, 'creativeTypes' ){ |x| reverse_type(x) }
47
59
  end
48
60
 
49
61
  def self.delete( auth, ids )
50
- ids = [ ids ] unless ids.is_a? Array
51
62
  body = { creativeIds: ids }
52
63
  response = request( auth, Service, 'deleteCreative', body )
53
64
  process( response, 'result' ){ |x| x }
54
65
  end
55
66
 
56
- def self.activate( auth, ids )
57
- ids = [ ids ] unless ids.is_a? Array
58
- body = { creativeIds: ids }
59
- response = request( auth, Service, 'activateCreative', body )
60
- process( response, 'creativeTypes' ){ |x| reverse_type(x) }
61
- end
62
-
63
- def self.status( auth, ids, type )
64
- ids = [ ids ] unless ids.is_a? Array
65
-
66
- type = case type
67
- when 'plan' then 3
68
- when 'group' then 5
69
- when 'creative' then 7
70
- else
71
- Exception.new( 'type must among: \'plan\',\'group\' and \'key\' ')
72
- end
73
-
74
- body = { ids: ids, type: type }
75
- response = request( auth, Service, 'getCreativeStatus', body )
76
- process( response, 'CreativeStatus' ){ |x| x }
77
- end
78
-
79
- def self.search_id_by_group_id( auth, ids, getTemp = 0 )
80
- '''
81
- \'getCreativeIdByAdgroupId\'
82
- @ input: group ids
83
- @ output: groupCreativeIds
84
- '''
85
- ids = [ ids ] unless ids.is_a? Array
86
- body = { adgroupIds: ids, getTemp: getTemp }
87
- response = request( auth, Service, 'getCreativeIdByAdgroupId', body )
88
- process( response, 'groupCreativeIds' ){ |x| make_groupCreativeIds( x ) }
89
- end
90
-
91
- def self.search_by_group_id( auth, ids, getTemp = 0 )
92
- ids = [ ids ] unless ids.is_a? Array
93
- body = { adgroupIds: ids, getTemp: getTemp }
94
- response = request( auth, Service, 'getCreativeByAdgroupId', body )
95
- process( response, 'groupCreatives' ){ |x| make_groupCreatives( x ) }
67
+ def self.enable( auth, ids )
68
+ creatives = ids.map{|id| {id: id, pause: false} }
69
+ self.update( auth, creatives )
96
70
  end
97
71
 
98
- private
99
- def self.make_groupCreativeIds( groupCreativeIds )
100
- group_creative_ids = []
101
- groupCreativeIds.each do |groupCreativeId|
102
- group_creative_id = { }
103
- group_creative_id[:group_id] = groupCreativeId['adgroupIds']
104
- group_creative_id[:creative_ids] = groupCreativeId['creativeIds']
105
- group_creative_ids << group_creative_id
106
- end
107
- return group_creative_ids
72
+ def self.pause( auth, ids )
73
+ creatives = ids.map{|id| {id: id, pause: true} }
74
+ self.update( auth, creatives )
108
75
  end
109
76
 
110
- private
111
- def self.make_groupCreatives( groupCreatives )
112
- group_creatives = []
113
- groupCreatives.each do |groupCreative |
114
- group_creative = {}
115
- group_creative[:group_id] = groupCreative['adgroupId']
116
- group_creative[:creatives] = reverse_type( groupCreative['creativeTypes'] )
117
- group_creatives << group_creative
118
- end
119
- return group_creatives
77
+ def self.status( auth, ids )
78
+ body = { ids: ids, idType: 7, creativeFields: [:creativeId, :status]}
79
+ response = request( auth, Service, 'getCreative', body )
80
+ process(response, 'groupCreatives' ){|x| reverse_type( x ) }
120
81
  end
121
82
 
122
83
  end
@@ -5,104 +5,73 @@ module PPC
5
5
  class Group< Baidu
6
6
  Service = 'Adgroup'
7
7
 
8
- @map =[
9
- [:plan_id, :campaignId],
10
- [:id, :adgroupId],
11
- [:name, :adgroupName],
12
- [:price, :maxPrice],
13
- [:negative, :negativeWords],
14
- [:exact_negative, :exactNegativeWords],
15
- [:pause, :pause],
16
- [:status, :status],
17
- [:reserved, :reserved]
18
- ]
8
+ GroupType = {
9
+ plan_id: :campaignId,
10
+ id: :adgroupId,
11
+ name: :adgroupName,
12
+ price: :maxPrice,
13
+ negative: :negativeWords,
14
+ exact_negative: :exactNegativeWords,
15
+ pause: :pause,
16
+ status: :status,
17
+ price_ratio: :priceRatio,
18
+ accu_price_factor: :accuPriceFactor,
19
+ word_price_factor: :wordPriceFactor,
20
+ wide_price_factor: :widePriceFactor,
21
+ match_price_status: :matchPriceStatus,
22
+ }
23
+ @map = GroupType
19
24
 
20
- def self.ids(auth )
21
- """
22
- @return : Array of campaignAdgroupIds
23
- """
24
- response = request( auth, Service , "getAllAdgroupId" )
25
- process( response, 'campaignAdgroupIds' ){ |x| make_planGroupIds( x ) }
25
+ def self.info( auth, ids)
26
+ body = {ids: ids, idType: 5, adgroupFields: GroupType.values}
27
+ response = request(auth, Service, "getAdgroup",body )
28
+ process( response, 'adgroupType' ){ |x| reverse_type( x )[0] }
29
+ end
30
+
31
+ def self.all( auth, plan_ids )
32
+ body = { ids: plan_ids, idType: 3, adgroupFields: GroupType.values}
33
+ response = request(auth, Service, 'getAdgroup', body)
34
+ process( response, 'campaignAdgroups' ){ |x|reverse_type(x) }
35
+ end
36
+
37
+ def self.ids( auth, plan_ids )
38
+ body = {ids: plan_ids, idType: 3, adgroupFields: [:adgroupId]}
39
+ response = request(auth, Service, "getAdgroup",body )
40
+ process( response, 'campaignAdgroupIds' ){ |x| reverse_type( x ) }
26
41
  end
27
42
 
28
43
  def self.get( auth, ids )
29
- ids = [ ids ] unless ids.is_a? Array
30
- body = { adgroupIds: ids }
31
- response = request(auth, Service, "getAdgroupByAdgroupId",body )
32
- process( response, 'adgroupTypes' ){ |x| reverse_type(x) }
44
+ body = {ids: ids, idType: 5, adgroupFields: GroupType.values}
45
+ response = request(auth, Service, "getAdgroup",body )
46
+ process( response, 'adgroupTypes' ){ |x| reverse_type( x ) }
33
47
  end
34
48
 
35
49
  def self.add( auth, groups )
36
- """
37
- @ input : one or list of AdgroupType
38
- @ output : list of AdgroupType
39
- """
40
- adgrouptypes = make_type( groups )
41
-
42
- body = {adgroupTypes: adgrouptypes }
43
-
50
+ body = {adgroupTypes: make_type( groups ) }
44
51
  response = request( auth, Service, "addAdgroup", body )
45
52
  process( response, 'adgroupTypes' ){ |x| reverse_type(x) }
46
53
  end
47
54
 
48
55
  def self.update( auth, groups )
49
- """
50
- @ input : one or list of AdgroupType
51
- @ output : list of AdgroupType
52
- """
53
- adgrouptypes = make_type( groups )
54
- body = {adgroupTypes: adgrouptypes}
55
-
56
+ body = {adgroupTypes: make_type( groups )}
56
57
  response = request( auth, Service, "updateAdgroup",body )
57
58
  process( response, 'adgroupTypes' ){ |x| reverse_type(x) }
58
59
  end
59
60
 
60
61
  def self.delete( auth, ids )
61
- """
62
- delete group body has no message
63
- """
64
- ids = [ ids ] unless ids.is_a? Array
65
62
  body = { adgroupIds: ids }
66
63
  response = request( auth, Service,"deleteAdgroup", body )
67
64
  process( response, 'nil' ){ |x| x }
68
65
  end
69
66
 
70
- def self.search_by_plan_id( auth, ids )
71
- ids = [ ids ] unless ids.class == Array
72
- body = { campaignIds: ids }
73
- response = request( auth, Service ,"getAdgroupByCampaignId", body )
74
- process( response, 'campaignAdgroups' ){ |x| make_planGroups( x ) }
75
- end
76
-
77
- def self.search_id_by_plan_id( auth, ids )
78
- ids = [ ids ] unless ids.class == Array
79
- body = { campaignIds: ids }
80
- response = request( auth, Service ,"getAdgroupIdByCampaignId", body )
81
- process( response, 'campaignAdgroupIds' ){ |x| make_planGroupIds( x ) }
82
- end
83
-
84
- private
85
- def self.make_planGroupIds( campaignAdgroupIds )
86
- planGroupIds = []
87
- campaignAdgroupIds.each do |campaignAdgroupId|
88
- planGroupId = { }
89
- planGroupId[:plan_id] = campaignAdgroupId['campaignId']
90
- planGroupId[:group_ids] = campaignAdgroupId['adgroupIds']
91
- planGroupIds << planGroupId
92
- end
93
- return planGroupIds
67
+ def self.enable( auth, ids )
68
+ groups = ids.map{|id| {id: id, pause: false} }
69
+ self.update( auth, groups )
94
70
  end
95
71
 
96
- private
97
- def self.make_planGroups( campaignAdgroups )
98
- planGroups = []
99
- campaignAdgroups.each do |campaignAdgroup|
100
- planGroup = {}
101
- planGroup[:plan_id] = campaignAdgroup['campaignId']
102
- planGroup[:groups] = reverse_type( campaignAdgroup['adgroupTypes'] )
103
- planGroups << planGroup
104
- end
105
- return planGroups
72
+ def self.pause( auth, ids )
73
+ groups = ids.map{|id| {id: id, pause: true} }
74
+ self.update( auth, groups )
106
75
  end
107
76
 
108
77
  end # class group