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
@@ -6,196 +6,103 @@ module PPC
6
6
  Service = 'Keyword'
7
7
 
8
8
  Match_type = { 'exact' => 1, 'phrase' => 2, 'wide' => 3,1 => 'exact', 2=> 'phrase' , 3 => 'wide' }
9
+ @match_types = Match_type
9
10
  Device = { 'pc' => 0, 'mobile' => 1, 'all' => 2 }
10
11
  Type = { 'plan' => 3, 'group' => 5, 'keyword' => 11 }
11
12
 
12
- @map = [
13
- [:id,:keywordId],
14
- [:group_id,:adgroupId],
15
- [:keyword,:keyword],
16
- [:price,:price],
17
- [:pc_destination,:pcDestinationUrl],
18
- [:mobile_destination,:mobileDestinationUrl],
19
- [:match_type,:matchType],
20
- [:phrase_type,:phraseType],
21
- [:status,:status],
22
- [:pause,:pause]
23
- ]
13
+ KeywordType = {
14
+ id: :keywordId,
15
+ group_id: :adgroupId,
16
+ plan_id: :campaignId,
17
+ keyword: :keyword,
18
+ price: :price,
19
+ pc_destination: :pcDestinationUrl,
20
+ mobile_destination: :mobileDestinationUrl,
21
+ match_type: :matchType,
22
+ phrase_type: :phraseType,
23
+ status: :status,
24
+ pause: :pause,
25
+ wmatchprefer: :wmatchprefer,
26
+ }
27
+ @map = KeywordType
28
+
29
+ KeywordQualityType = {
30
+ id: :id,
31
+ group_id: :adgroupId,
32
+ plan_id: :campaignId,
33
+ pc_quality: :pcQuality,
34
+ pc_reliable: :pcReliable,
35
+ pc_reason: :pcReason,
36
+ pc_scale: :pcScale,
37
+ mobile_quality: :mobileQuality,
38
+ mobile_reliable: :mobileReliable,
39
+ mobile_reason: :mobileReason,
40
+ mobile_scale: :mobileScale,
41
+ }
42
+ @quality10_map = KeywordQualityType
43
+
44
+ def self.info( auth, ids )
45
+ body = { ids: ids, idType: 11, wordFields: KeywordType.values}
46
+ response = request( auth, Service, 'getWord', body )
47
+ process(response, 'keywordType' ){|x| reverse_type( x )[0] }
48
+ end
49
+
50
+ def self.all( auth, group_ids )
51
+ body = { ids: group_ids, idType: 5, wordFields: KeywordType.values}
52
+ response = request( auth, Service, 'getWord', body )
53
+ process(response, 'groupKeywords' ){|x| reverse_type( x ) }
54
+ end
24
55
 
25
- @quality10_map = [
26
- [ :id, :id ],
27
- [ :group_id, :adgroupId ],
28
- [ :plan_id, :Campaigned ],
29
- [ :pc_quality, :pcQuality ],
30
- [ :pc_reliable, :pcReliable ],
31
- [ :pc_reason, :pcReason ],
32
- [ :pc_scale, :pcScale ],
33
- [ :mobile_quality, :mobileQuality ],
34
- [ :mobile_reliable, :mobileReliable ],
35
- [ :mobile_reason, :mobileReason ],
36
- [ :mobile_scale, :mobileScale ]
37
- ]
56
+ def self.ids( auth, group_ids )
57
+ body = { ids: group_ids, idType: 5, wordFields: [:keywordId]}
58
+ response = request( auth, Service, 'getWord', body )
59
+ process(response, 'groupKeywordIds' ){|x| reverse_type( x ) }
60
+ end
38
61
 
39
- # 后面改成info方法
40
62
  def self.get( auth, ids )
41
- '''
42
- getKeywordByKeywordId
43
- '''
44
- ids = [ ids ] unless ids.is_a? Array
45
- body = { keywordIds: ids}
46
- response = request( auth, Service, 'getKeywordByKeywordId', body )
47
- return process(response, 'keywordTypes' ){|x| reverse_type( x ) }
63
+ body = { ids: ids, idType: 11, wordFields: KeywordType.values}
64
+ response = request( auth, Service, 'getWord', body )
65
+ process(response, 'keywordTypes' ){|x| reverse_type( x ) }
48
66
  end
49
67
 
50
68
  def self.add( auth, keywords )
51
- '''
52
- '''
53
- keywordtypes = make_type( keywords )
54
- body = { keywordTypes: keywordtypes }
55
- response = request( auth, Service, "addKeyword", body )
56
- return process(response, 'keywordTypes' ){|x| reverse_type(x) }
69
+ body = { keywordTypes: make_type( keywords ) }
70
+ response = request( auth, Service, "addWord", body )
71
+ process(response, 'keywordTypes' ){|x| reverse_type(x) }
57
72
  end
58
73
 
59
74
  def self.update( auth, keywords )
60
- '''
61
- '''
62
- keywordtypes = make_type( keywords )
63
- body = { keywordTypes: keywordtypes }
64
- response = request( auth, Service, "updateKeyword", body )
65
- return process(response, 'keywordTypes' ){|x| reverse_type(x) }
75
+ body = { keywordTypes: make_type( keywords ) }
76
+ response = request( auth, Service, "updateWord", body )
77
+ process(response, 'keywordTypes' ){|x| reverse_type(x) }
66
78
  end
67
79
 
68
80
  def self.delete( auth, ids )
69
- """
70
- """
71
- ids = [ ids ] unless ids.is_a? Array
72
81
  body = { keywordIds: ids}
73
- response = request( auth, Service, 'deleteKeyword', body )
74
- return process(response, 'result' ){|x| x }
75
- end
76
-
77
- def self.activate( auth, ids )
78
- """
79
- """
80
- ids = [ ids ] unless ids.is_a? Array
81
- body = { keywordIds: ids }
82
- response = request( auth, Service, 'activateKeyword', body)
83
- return process(response, 'keywordTypes' ){|x| reverse_type(x) }
84
- end
85
-
86
- def self.search_by_group_id( auth, group_ids )
87
- """
88
- getKeywordByGroupIds
89
- @input: list of group id
90
- @output: list of groupKeyword
91
- """
92
- group_ids = [ group_ids ] unless group_ids.is_a? Array
93
- body = { adgroupIds: group_ids }
94
- response = request( auth, Service, "getKeywordByAdgroupId", body )
95
- return process(response, 'groupKeywords' ){|x| make_groupKeywords( x ) }
96
- end
97
-
98
- def self.search_id_by_group_id( auth, group_ids )
99
- group_ids = [ group_ids ] unless group_ids.is_a? Array
100
- body = { adgroupIds: group_ids }
101
- response = request( auth, Service, "getKeywordIdByAdgroupId", body )
102
- return process(response, 'groupKeywordIds' ){|x| make_groupKeywordIds( x ) }
103
- end
104
-
105
- # 下面三个操作操作对象包括计划,组和关键字
106
- # 不知道放在这里合不合适
107
- def self.status( auth, ids, type )
108
- '''
109
- Return [{ id: id, status: status } ... ]
110
- '''
111
- ids = [ ids ] unless ids.is_a? Array
112
- body = { ids: ids, type: Type[type]}
113
- response = request( auth, Service, 'getKeywordStatus', body )
114
- return process(response, 'keywordStatus' ){ |statusTypes|
115
- statusTypes = [statusTypes] unless statusTypes.is_a? Array
116
- status =[]
117
-
118
- statusTypes.each do |statusType|
119
- status << { id: statusType['id'], status: statusType['status'] }
120
- end
121
- return status
122
- }
123
- end
124
-
125
- def self.quality( auth ,ids, type, device )
126
- '''
127
- Return 10Quanlity *Not the old Quality* of given ketword id
128
- '''
129
- ids = [ ids ] unless ids.is_a? Array
130
- body = { ids: ids, type: Type[type], device:Device[device] }
131
- response = request( auth, Service, 'getKeyword10Quality', body )
132
- return process(response, 'keyword10Quality' ){|x| reverse_type( x, @quality10_map ) }
82
+ response = request( auth, Service, 'deleteWord', body )
83
+ process(response, 'result' ){|x| x }
133
84
  end
134
85
 
135
- private
136
- def self.make_groupKeywordIds( groupKeywordIds )
137
- group_keyword_ids = []
138
- groupKeywordIds.each do |groupKeywordId|
139
- group_keyword_id = { }
140
- group_keyword_id[:group_id] = groupKeywordId['adgroupIds']
141
- group_keyword_id[:keyword_ids] = groupKeywordId['keywordIds']
142
- group_keyword_ids << group_keyword_id
143
- end
144
- return group_keyword_ids
86
+ def self.enable( auth, ids )
87
+ keywords = ids.map{|id| {id: id, pause: false} }
88
+ self.update( auth, keywords )
145
89
  end
146
90
 
147
- private
148
- def self.make_groupKeywords( groupKeywords )
149
- group_keywords = []
150
- groupKeywords.each do |groupKeyword|
151
- group_keyword = {}
152
- group_keyword[:group_id] = groupKeyword['adgroupId']
153
- group_keyword[:keywords] = reverse_type( groupKeyword['keywordTypes'] )
154
- group_keywords << group_keyword
155
- end
156
- return group_keywords
91
+ def self.pause( auth, ids )
92
+ keywords = ids.map{|id| {id: id, pause: true} }
93
+ self.update( auth, keywords )
157
94
  end
158
95
 
159
- # Override
160
- def self.make_type( params, map = @map)
161
- params = [ params ] unless params.is_a? Array
162
- types = []
163
- params.each do |param|
164
- type = {}
165
- map.each do |key|
166
- # 增加对matchtype的自动转换
167
- if key[0] == :match_type
168
- value = param[ key[0] ]
169
- type[ key[1] ] = Match_type[ value ] if value
170
- else
171
- value = param[ key[0] ]
172
- type[ key[1] ] = value if value
173
- end
174
- end
175
- types << type
176
- end
177
- return types
96
+ def self.status( auth, ids )
97
+ body = { ids: ids, idType: 11, keywordTypes: [:keywordId, :status]}
98
+ response = request( auth, Service, 'getWord', body )
99
+ process(response, 'groupKeywords' ){|x| reverse_type( x ) }
178
100
  end
179
101
 
180
- # Overwrite
181
- def self.reverse_type( types, map = @map )
182
- types = [ types ] unless types.is_a? Array
183
- params = []
184
- types.each do |type|
185
- param = {}
186
- # 增加对matchtype的自动转换
187
- map.each do |key|
188
- if key[0] == :match_type
189
- value = type[ key[1].to_s ]
190
- param[ key[0] ] = Match_type[ value ] if value
191
- else
192
- value = type[ key[1].to_s ]
193
- param[ key[0] ] = value if value
194
- end
195
- end # map.each
196
- params << param
197
- end # types.each
198
- return params
102
+ def self.quality( auth, ids )
103
+ body = { ids: ids, idType: 11, keywordTypes: KeywordQualityType.values}
104
+ response = request( auth, Service, 'getWord', body )
105
+ process(response, 'groupKeywords' ){|x| reverse_type( x , KeywordQualityType) }
199
106
  end
200
107
 
201
108
  end # keyword
@@ -5,12 +5,13 @@ module PPC
5
5
  class Phone < Baidu
6
6
  Service = 'NewCreative'
7
7
 
8
- @map =[
9
- [:id,:phoneId],
10
- [:group_id,:adgroupId],
11
- [:phone_num,:phoneNum],
12
- [:pause,:pause],
13
- ]
8
+ PhoneType = {
9
+ id: :phoneId,
10
+ group_id: :adgroupId,
11
+ phone_num: :phoneNum,
12
+ pause: :pause,
13
+ }
14
+ @map = PhoneType
14
15
 
15
16
  def self.update( auth, phones )
16
17
  '''
@@ -21,7 +22,7 @@ module PPC
21
22
  process( response, 'phoneTypes' ){ |x| reverse_type(x) }
22
23
  end
23
24
 
24
- def self.search_id_by_group_id( auth, ids, getTemp = 0 )
25
+ def self.ids( auth, ids, getTemp = 0 )
25
26
  '''
26
27
  \'getPhoneIdByAdgroupId\'
27
28
  @ input: group ids
@@ -4,63 +4,80 @@ module PPC
4
4
  class Plan< Baidu
5
5
  Service = 'Campaign'
6
6
 
7
- @map = [
8
- [:id,:campaignId],
9
- [:name,:campaignName],
10
- [:budget,:budget],
11
- [:region,:regionTarget],
12
- [:ip,:excludeIp] ,
13
- [:negative,:negativeWords],
14
- [:exact_negative,:exactNegativeWords],
15
- [:schedule,:schedule],
16
- [:budget_offline_time,:budgetOfflineTime],
17
- [:show_prob,:showProb],
18
- [:device,:device],
19
- [:price_ratio,:priceRatio],
20
- [:is_dynamic,:isDynamicCreative],
21
- [:pause,:pause],
22
- [:status,:status]
23
- ]
7
+ PlanType = {
8
+ id: :campaignId,
9
+ name: :campaignName,
10
+ budget: :budget,
11
+ region: :regionTarget,
12
+ negative: :negativeWords,
13
+ exact_negative: :exactNegativeWords,
14
+ schedule: :schedule,
15
+ budget_offline_time: :budgetOfflineTime,
16
+ show_prob: :showProb,
17
+ device: :device,
18
+ price_ratio: :priceRatio,
19
+ is_dynamic: :isDynamicCreative,
20
+ pause: :pause,
21
+ status: :status,
22
+ rmkt_status: :rmktStatus,
23
+ type: :campaignType,
24
+ isdynamictagsublink: :isDynamicTagSublink,
25
+ isdynamichotredirect: :isDynamicHotRedirect,
26
+ isdynamictitle: :isDynamicTitle,
27
+ rmkt_price_ratio: :rmktPriceRatio,
28
+ }
29
+ @map = PlanType
30
+
31
+ def self.info( auth, ids )
32
+ body = { campaignIds: ids, campaignFields: PlanType.values}
33
+ response = request(auth,Service,'getCampaign',body)
34
+ process( response, 'campaignType' ){ |x|reverse_type(x)[0] }
35
+ end
24
36
 
25
37
  def self.all( auth )
26
- response = request( auth, Service, 'getAllCampaign' )
27
- process( response, 'campaignTypes' ){ |x| reverse_type(x) }
38
+ body = { campaignIds: nil, campaignFields: PlanType.values}
39
+ response = request(auth,Service,'getCampaign',body)
40
+ process( response, 'campaignTypes' ){ |x|reverse_type(x) }
28
41
  end
29
42
 
30
43
  def self.ids( auth )
31
- response = request( auth, Service, 'getAllCampaignId' )
32
- process( response, 'campaignIds' ){ |x| x }
44
+ body = { campaignIds: nil, campaignFields: ["campaignId"]}
45
+ response = request(auth,Service,'getCampaign',body)
46
+ process( response, 'campaignIds' ){ |x|reverse_type(x) }
33
47
  end
34
48
 
35
49
  def self.get( auth, ids )
36
- ids = [ ids ] unless ids.is_a? Array
37
- body = { campaignIds: ids }
38
- response = request( auth, Service, 'getCampaignByCampaignId', body)
39
- process( response, 'campaignTypes' ){ |x| reverse_type(x) }
50
+ body = { campaignIds: ids, campaignFields: PlanType.values}
51
+ response = request( auth, Service, 'getCampaign', body)
52
+ process( response, 'campaignTypes' ){ |x| reverse_type(x)}
40
53
  end
41
54
 
42
55
  def self.add( auth, plans )
43
- campaigntypes = make_type( plans )
44
- # set extended = 1 to allow change of isDynamicCreative
45
- body = { campaignTypes: campaigntypes, extended:1 }
56
+ body = { campaignTypes: make_type( plans ) }
46
57
  response = request( auth, Service, 'addCampaign', body)
47
58
  process( response, 'campaignTypes' ){ |x| reverse_type(x) }
48
59
  end
49
60
 
50
61
  def self.update(auth,plans )
51
- campaigntypes = make_type( plans )
52
- # set extended = 1 to allow change of isDynamicCreative
53
- body = { campaignTypes: campaigntypes, extended:1 }
62
+ body = { campaignTypes: make_type( plans ) }
54
63
  response = request( auth, Service, 'updateCampaign', body)
55
64
  process( response, 'campaignTypes' ){ |x| reverse_type(x) }
56
65
  end
57
66
 
58
67
  def self.delete(auth, ids )
59
- ids = [ ids ] unless ids.class == Array
60
- body = { campaignIds: ids }
61
- response = request( auth, Service, 'deleteCampaign', body)
68
+ response = request( auth, Service, 'deleteCampaign', {campaignIds: ids} )
62
69
  process( response, 'result' ){ |x| x }
63
70
  end
71
+
72
+ def self.enable( auth, ids )
73
+ plans = ids.map{|id| {id: id, pause: false} }
74
+ self.update( auth, plans )
75
+ end
76
+
77
+ def self.pause( auth, ids )
78
+ plans = ids.map{|id| {id: id, pause: true} }
79
+ self.update( auth, plans )
80
+ end
64
81
 
65
82
  end # Service
66
83
  end # baidu
@@ -25,7 +25,7 @@ module PPC
25
25
  request = make_reportrequest( params )
26
26
  body = { reportRequestType: request }
27
27
  response = request( auth, Service, 'getProfessionalReportId' ,body)
28
- process( response, 'reportId' ){ |x| x }
28
+ process( response, 'reportId' ){ |x| x[0]["reportId"] }
29
29
  end
30
30
 
31
31
  def self.get_state( auth, id )
@@ -35,13 +35,13 @@ module PPC
35
35
  status = {1=>'Waiting' ,2=>'Opearting' ,3=>'Finished'}
36
36
  body = { reportId: id }
37
37
  response = request( auth, Service, 'getReportState' ,body)
38
- process( response, 'isGenerated' ){ |x| status[x] }
38
+ process( response, 'isGenerated' ){ |x| status[x[0]["isGenerated"]] }
39
39
  end
40
40
 
41
41
  def self.get_url( auth, id )
42
42
  body = { reportId: id }
43
43
  response = request( auth, Service, 'getReportFileUrl' ,body)
44
- process( response, 'reportFilePath' ){ |x| x }
44
+ process( response, 'reportFilePath' ){ |x| x[0]["reportFilePath"] }
45
45
  end
46
46
 
47
47
  private
@@ -63,33 +63,15 @@ module PPC
63
63
  requesttype[:unitOfTime] = Unit_map[ param[:unit] ] if param[:unit]
64
64
  requesttype[:device] = Device_map[ param[:device] ] if param[:device]
65
65
  requesttype[:idOnly] = param[:id_only] || false
66
- requesttype[:startDate] = parse_date( param[:startDate] )
67
- requesttype[:endDate] = parse_date( param[:endDate] )
68
- return requesttype
69
- end
70
-
71
- private
72
- def self.parse_date( date )
73
- """
74
- Cast string to time:
75
- 'YYYYMMDD' => Time
76
- """
77
- if date
78
- y = date[0..3]
79
- m = date[4..5]
80
- d = date[6..7]
81
- date = Time.new( y, m, d )
82
- else
83
- date = (Time.now - 24*3600)
84
- end
85
- date
66
+ requesttype[:startDate] = Time.parse( param[:startDate] ) rescue Time.now - 86400
67
+ requesttype[:endDate] = Time.parse( param[:endDate] ) rescue Time.now - 86400
68
+ requesttype
86
69
  end
87
70
 
88
71
  #################################
89
72
  # useful function for operation #
90
73
  #################################
91
- def self.query_report( auth, param = nil, debug = false )
92
- param = {} if not param
74
+ def self.query_report( auth, param = {}, debug = false )
93
75
  param[:type] ||= 'query'
94
76
  param[:fields] ||= %w(click impression)
95
77
  param[:level] ||= 'pair'
@@ -98,8 +80,7 @@ module PPC
98
80
  download_report( auth, param, debug )
99
81
  end
100
82
 
101
- def self.creative_report( auth, param = nil, debug = false )
102
- param = {} if not param
83
+ def self.creative_report( auth, param = {}, debug = false )
103
84
  param[:type] ||= 'creative'
104
85
  param[:fields] ||= %w(impression click cpc cost ctr cpm position conversion)
105
86
  param[:level] ||= 'creative'
@@ -108,8 +89,7 @@ module PPC
108
89
  download_report( auth, param, debug )
109
90
  end
110
91
 
111
- def self.keyword_report( auth, param = nil, debug = false )
112
- param = {} if not param
92
+ def self.keyword_report( auth, param = {}, debug = false )
113
93
  param[:type] ||= 'keyword'
114
94
  param[:fields] ||= %w(impression click cpc cost ctr cpm position conversion)
115
95
  param[:level] ||= 'keywordid'