ppc 0.3.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.
- checksums.yaml +7 -0
- data/.gitignore +37 -0
- data/.rspec +2 -0
- data/LICENSE +339 -0
- data/README.md +78 -0
- data/lib/ppc.rb +17 -0
- data/lib/ppc/api.rb +10 -0
- data/lib/ppc/api/baidu.rb +138 -0
- data/lib/ppc/api/baidu/account.rb +47 -0
- data/lib/ppc/api/baidu/bulk.rb +41 -0
- data/lib/ppc/api/baidu/creative.rb +125 -0
- data/lib/ppc/api/baidu/group.rb +111 -0
- data/lib/ppc/api/baidu/keyword.rb +204 -0
- data/lib/ppc/api/baidu/plan.rb +68 -0
- data/lib/ppc/api/baidu/report.rb +143 -0
- data/lib/ppc/api/qihu.rb +107 -0
- data/lib/ppc/api/qihu/account.rb +86 -0
- data/lib/ppc/api/qihu/creative.rb +106 -0
- data/lib/ppc/api/qihu/group.rb +113 -0
- data/lib/ppc/api/qihu/keyword.rb +111 -0
- data/lib/ppc/api/qihu/plan.rb +64 -0
- data/lib/ppc/api/qihu/report.rb +159 -0
- data/lib/ppc/api/shenma.rb +64 -0
- data/lib/ppc/api/shenma/report.rb +135 -0
- data/lib/ppc/api/sogou.rb +122 -0
- data/lib/ppc/api/sogou/account.rb +42 -0
- data/lib/ppc/api/sogou/creative.rb +117 -0
- data/lib/ppc/api/sogou/group.rb +116 -0
- data/lib/ppc/api/sogou/keyword.rb +182 -0
- data/lib/ppc/api/sogou/plan.rb +66 -0
- data/lib/ppc/api/sogou/report.rb +129 -0
- data/lib/ppc/ext.rb +9 -0
- data/lib/ppc/operation.rb +196 -0
- data/lib/ppc/operation/account.rb +53 -0
- data/lib/ppc/operation/creative.rb +28 -0
- data/lib/ppc/operation/group.rb +59 -0
- data/lib/ppc/operation/keyword.rb +32 -0
- data/lib/ppc/operation/plan.rb +47 -0
- data/lib/ppc/operation/report.rb +19 -0
- data/ppc.gemspec +26 -0
- data/spec/baidu/api_baidu_account_spec.rb +15 -0
- data/spec/baidu/api_baidu_creative_spec.rb +67 -0
- data/spec/baidu/api_baidu_group_spec.rb +45 -0
- data/spec/baidu/api_baidu_keyword_spec.rb +61 -0
- data/spec/baidu/api_baidu_plan_spec.rb +43 -0
- data/spec/baidu/api_baidu_report_spec.rb +44 -0
- data/spec/baidu/api_baidu_spec.rb +55 -0
- data/spec/operation/operation_baidu_report_spec.rb +17 -0
- data/spec/operation/operation_baidu_spec.rb +78 -0
- data/spec/operation/operation_qihu_report_spec.rb +18 -0
- data/spec/operation/operation_qihu_spec.rb +51 -0
- data/spec/operation/operation_sogou_report_spec.rb +17 -0
- data/spec/operation/operation_sogou_spec.rb +51 -0
- data/spec/operation/operation_spec_helper.rb +51 -0
- data/spec/qihu/api_qihu_account_spec.rb +25 -0
- data/spec/qihu/api_qihu_creative_spec.rb +48 -0
- data/spec/qihu/api_qihu_group_spec.rb +40 -0
- data/spec/qihu/api_qihu_keyword_spec.rb +50 -0
- data/spec/qihu/api_qihu_plan_spec.rb +39 -0
- data/spec/qihu/api_qihu_report_spec.rb +54 -0
- data/spec/sogou/api_sogou_account_spec.rb +15 -0
- data/spec/sogou/api_sogou_creative_spec.rb +48 -0
- data/spec/sogou/api_sogou_group_spec.rb +45 -0
- data/spec/sogou/api_sogou_keyword_spec.rb +50 -0
- data/spec/sogou/api_sogou_plan_spec.rb +39 -0
- data/spec/sogou/api_sogou_report_spec.rb +51 -0
- data/spec/spec_helper.rb +134 -0
- metadata +177 -0
@@ -0,0 +1,204 @@
|
|
1
|
+
# -*- coding:utf-8 -*-
|
2
|
+
module PPC
|
3
|
+
module API
|
4
|
+
class Baidu
|
5
|
+
class Keyword< Baidu
|
6
|
+
Service = 'Keyword'
|
7
|
+
|
8
|
+
Match_type = { 'exact' => 1, 'pharse' => 2, 'wide' => 3,1 => 'exact', 2=> 'pharse' , 3 => 'wide' }
|
9
|
+
Device = { 'pc' => 0, 'mobile' => 1, 'all' => 2 }
|
10
|
+
Type = { 'plan' => 3, 'group' => 5, 'keyword' => 11 }
|
11
|
+
|
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
|
+
]
|
24
|
+
|
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
|
+
]
|
38
|
+
|
39
|
+
# 后面改成info方法
|
40
|
+
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 ) }
|
48
|
+
end
|
49
|
+
|
50
|
+
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) }
|
57
|
+
end
|
58
|
+
|
59
|
+
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) }
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.delete( auth, ids )
|
69
|
+
"""
|
70
|
+
"""
|
71
|
+
ids = [ ids ] unless ids.is_a? Array
|
72
|
+
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 ) }
|
133
|
+
end
|
134
|
+
|
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
|
145
|
+
end
|
146
|
+
|
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
|
157
|
+
end
|
158
|
+
|
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
|
178
|
+
end
|
179
|
+
|
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
|
199
|
+
end
|
200
|
+
|
201
|
+
end # keyword
|
202
|
+
end # Baidu
|
203
|
+
end # API
|
204
|
+
end # PPC
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module PPC
|
2
|
+
module API
|
3
|
+
class Baidu
|
4
|
+
class Plan< Baidu
|
5
|
+
Service = 'Campaign'
|
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
|
+
]
|
24
|
+
|
25
|
+
def self.all( auth )
|
26
|
+
response = request( auth, Service, 'getAllCampaign' )
|
27
|
+
process( response, 'campaignTypes' ){ |x| reverse_type(x) }
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.ids( auth )
|
31
|
+
response = request( auth, Service, 'getAllCampaignId' )
|
32
|
+
process( response, 'campaignIds' ){ |x| x }
|
33
|
+
end
|
34
|
+
|
35
|
+
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) }
|
40
|
+
end
|
41
|
+
|
42
|
+
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 }
|
46
|
+
response = request( auth, Service, 'addCampaign', body)
|
47
|
+
process( response, 'campaignTypes' ){ |x| reverse_type(x) }
|
48
|
+
end
|
49
|
+
|
50
|
+
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 }
|
54
|
+
response = request( auth, Service, 'updateCampaign', body)
|
55
|
+
process( response, 'campaignTypes' ){ |x| reverse_type(x) }
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.delete(auth, ids )
|
59
|
+
ids = [ ids ] unless ids.class == Array
|
60
|
+
body = { campaignIds: ids }
|
61
|
+
response = request( auth, Service, 'deleteCampaign', body)
|
62
|
+
process( response, 'result' ){ |x| x }
|
63
|
+
end
|
64
|
+
|
65
|
+
end # Service
|
66
|
+
end # baidu
|
67
|
+
end # API
|
68
|
+
end # PPC
|
@@ -0,0 +1,143 @@
|
|
1
|
+
# -*- coding:utf-8 -*-
|
2
|
+
module PPC
|
3
|
+
module API
|
4
|
+
class Baidu
|
5
|
+
class Report< Baidu
|
6
|
+
Service = 'Report'
|
7
|
+
|
8
|
+
# 需要用到的映射集合
|
9
|
+
Type_map = { 'account' => 2, 'plan'=> 10, 'group'=> 11,
|
10
|
+
'keyword'=> 14, 'creative'=> 12, 'pair'=> 15,
|
11
|
+
'region'=> 3, 'wordid'=> 9 , 'query'=>6 }
|
12
|
+
|
13
|
+
Level_map = { 'account' => 2, 'plan' => 3, 'group' => 5,
|
14
|
+
'creative'=> 7, 'keywordid' => 11, 'pair' => 12,
|
15
|
+
'wordid' => 6 }
|
16
|
+
|
17
|
+
Device_map = { 'all' => 0, 'pc' => 1, 'mobile' => 2 }
|
18
|
+
|
19
|
+
Unit_map = { 'day' => 5, 'week' => 4, 'month' => 3, 'year' => 1, 'hour' => 7 }
|
20
|
+
|
21
|
+
########################
|
22
|
+
# API wraping function #
|
23
|
+
########################
|
24
|
+
def self.get_id( auth, params )
|
25
|
+
request = make_reportrequest( params )
|
26
|
+
body = { reportRequestType: request }
|
27
|
+
response = request( auth, Service, 'getProfessionalReportId' ,body)
|
28
|
+
process( response, 'reportId' ){ |x| x }
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.get_state( auth, id )
|
32
|
+
'''
|
33
|
+
input id should be string
|
34
|
+
'''
|
35
|
+
status = {1=>'Waiting' ,2=>'Opearting' ,3=>'Finished'}
|
36
|
+
body = { reportId: id }
|
37
|
+
response = request( auth, Service, 'getReportState' ,body)
|
38
|
+
process( response, 'isGenerated' ){ |x| status[x] }
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.get_url( auth, id )
|
42
|
+
body = { reportId: id }
|
43
|
+
response = request( auth, Service, 'getReportFileUrl' ,body)
|
44
|
+
process( response, 'reportFilePath' ){ |x| x }
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
def self.make_reportrequest( param )
|
49
|
+
"""
|
50
|
+
make RepoerRequestType
|
51
|
+
==============
|
52
|
+
@Input : :fields,:type,:level,:range,:unit,:device,:id_only,:startDate:endDate
|
53
|
+
==============
|
54
|
+
Note:
|
55
|
+
We cast [ type, level, range, unit,device ] from int to string.
|
56
|
+
For more information please see those map at the begining of the file
|
57
|
+
"""
|
58
|
+
requesttype = {}
|
59
|
+
requesttype[:performanceData] = param[:fields] || %w(click impression)
|
60
|
+
requesttype[:reportType] = Type_map[ param[:type] ] if param[:type]
|
61
|
+
requesttype[:levelOfDetails] = Level_map[ param[:level] ] if param[:level]
|
62
|
+
requesttype[:statRange] = Level_map[ param[:range] ] if param[:range]
|
63
|
+
requesttype[:unitOfTime] = Unit_map[ param[:unit] ] if param[:unit]
|
64
|
+
requesttype[:device] = Device_map[ param[:device] ] if param[:device]
|
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
|
86
|
+
end
|
87
|
+
|
88
|
+
#################################
|
89
|
+
# useful function for operation #
|
90
|
+
#################################
|
91
|
+
def self.query_report( auth, param = nil, debug = false )
|
92
|
+
param = {} if not param
|
93
|
+
param[:type] ||= 'query'
|
94
|
+
param[:fields] ||= %w(click impression)
|
95
|
+
param[:level] ||= 'pair'
|
96
|
+
param[:range] ||= 'account'
|
97
|
+
param[:unit] ||= 'day'
|
98
|
+
download_report( auth, param, debug )
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.creative_report( auth, param = nil, debug = false )
|
102
|
+
param = {} if not param
|
103
|
+
param[:type] ||= 'creative'
|
104
|
+
param[:fields] ||= %w(impression click cpc cost ctr cpm position conversion)
|
105
|
+
param[:level] ||= 'creative'
|
106
|
+
param[:range] ||= 'creative'
|
107
|
+
param[:unit] ||= 'day'
|
108
|
+
download_report( auth, param, debug )
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.keyword_report( auth, param = nil, debug = false )
|
112
|
+
param = {} if not param
|
113
|
+
param[:type] ||= 'keyword'
|
114
|
+
param[:fields] ||= %w(impression click cpc cost ctr cpm position conversion)
|
115
|
+
param[:level] ||= 'keywordid'
|
116
|
+
param[:range] ||= 'keywordid'
|
117
|
+
param[:unit] ||= 'day'
|
118
|
+
download_report( auth, param, debug )
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.download_report( auth, param, debug = false )
|
122
|
+
p param
|
123
|
+
response = get_id( auth, param )
|
124
|
+
if response[:succ]
|
125
|
+
id = response[:result]
|
126
|
+
p "Got report id:" + id.to_s if debug
|
127
|
+
loop do
|
128
|
+
sleep 2
|
129
|
+
break if get_state( auth, id )[:result] == 'Finished'
|
130
|
+
p "Report is not generated, waiting..." if debug
|
131
|
+
end
|
132
|
+
|
133
|
+
url = get_url( auth, id )[:result]
|
134
|
+
return open(url).read.force_encoding('gb18030').encode('utf-8')
|
135
|
+
else
|
136
|
+
raise response[:failure][0]["message"]
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
end # Repost
|
141
|
+
end # Baidu
|
142
|
+
end # API
|
143
|
+
end # PPC
|
data/lib/ppc/api/qihu.rb
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
# -*- coding:utf-8 -*-
|
2
|
+
require 'ppc/api/qihu/account'
|
3
|
+
require 'ppc/api/qihu/plan'
|
4
|
+
require 'ppc/api/qihu/group'
|
5
|
+
require 'ppc/api/qihu/keyword'
|
6
|
+
require 'ppc/api/qihu/creative'
|
7
|
+
require 'ppc/api/qihu/report'
|
8
|
+
require 'httparty'
|
9
|
+
require 'json'
|
10
|
+
|
11
|
+
module PPC
|
12
|
+
module API
|
13
|
+
class Qihu
|
14
|
+
|
15
|
+
def self.request( auth, service, method, params = {} )
|
16
|
+
url = "https://api.e.360.cn/2.0/#{service}/#{method}"
|
17
|
+
# 日后考虑将httpparty用Net/http代替
|
18
|
+
response = HTTParty.post(url,
|
19
|
+
body: params,
|
20
|
+
headers: {'apiKey' => auth[:token],
|
21
|
+
'accessToken' => auth[:accessToken],
|
22
|
+
'serveToken' => Time.now.to_i.to_s }
|
23
|
+
)
|
24
|
+
response.parsed_response
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.process( response, key, failure_key = '', &func )
|
28
|
+
response_key = response.keys[0]
|
29
|
+
content = response[ response_key ]
|
30
|
+
# special case solution
|
31
|
+
if content == nil
|
32
|
+
return{ succ:true, failure:nil, result:nil }
|
33
|
+
end
|
34
|
+
|
35
|
+
result = { }
|
36
|
+
if content['failures'] != nil
|
37
|
+
result[:succ] = false
|
38
|
+
result[:failure] = content['failures']['item']
|
39
|
+
result[:result] = nil
|
40
|
+
else
|
41
|
+
result[:succ] = true
|
42
|
+
result[:result] = func[ key==''? content : content[ key ] ]
|
43
|
+
result[:failure] = failure_key == ''? nil : content[ failure_key ]
|
44
|
+
end
|
45
|
+
return result
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.to_json_string( items )
|
49
|
+
'''
|
50
|
+
convert list of string/int to list of json string
|
51
|
+
'''
|
52
|
+
return '' if items == nil
|
53
|
+
items = [items] unless items.is_a? Array
|
54
|
+
items_str = []
|
55
|
+
items.each{ |x| items_str << x.to_s }
|
56
|
+
items_str.to_json
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.to_id_list( ids_str )
|
60
|
+
return [] if ids_str == nil
|
61
|
+
ids_str = [ids_str] unless ids_str.is_a? Array
|
62
|
+
ids_i = []
|
63
|
+
ids_str.each{ |id| ids_i<<id.to_i }
|
64
|
+
ids_i
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.make_type( params, map = @map)
|
68
|
+
'''
|
69
|
+
'''
|
70
|
+
params = [ params ] unless params.is_a? Array
|
71
|
+
|
72
|
+
types = []
|
73
|
+
params.each do |param|
|
74
|
+
type = {}
|
75
|
+
|
76
|
+
map.each do |key|
|
77
|
+
value = param[ key[0] ]
|
78
|
+
type[ key[1] ] = value if value != nil
|
79
|
+
end
|
80
|
+
|
81
|
+
types << type
|
82
|
+
end
|
83
|
+
return types
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.reverse_type( types, map = @map )
|
87
|
+
'''
|
88
|
+
'''
|
89
|
+
types = [ types ] unless types.is_a? Array
|
90
|
+
|
91
|
+
params = []
|
92
|
+
types.each do |type|
|
93
|
+
param = {}
|
94
|
+
|
95
|
+
map.each do |key|
|
96
|
+
value = type[ key[1].to_s ]
|
97
|
+
param[ key[0] ] = value if value != nil
|
98
|
+
end
|
99
|
+
|
100
|
+
params << param
|
101
|
+
end
|
102
|
+
return params
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|