ppc 1.3.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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