ppc 0.3.0 → 1.0.1
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 +4 -4
- data/.autotest +25 -0
- data/.gemtest +0 -0
- data/History.txt +6 -0
- data/Manifest.txt +8 -0
- data/README.txt +80 -0
- data/Rakefile +19 -0
- data/bin/ppc +3 -0
- data/lib/ppc.rb +6 -15
- data/test/test_ppc.rb +0 -0
- metadata +41 -130
- data/.gitignore +0 -37
- data/.rspec +0 -2
- data/LICENSE +0 -339
- data/README.md +0 -78
- data/lib/ppc/api.rb +0 -10
- data/lib/ppc/api/baidu.rb +0 -138
- data/lib/ppc/api/baidu/account.rb +0 -47
- data/lib/ppc/api/baidu/bulk.rb +0 -41
- data/lib/ppc/api/baidu/creative.rb +0 -125
- data/lib/ppc/api/baidu/group.rb +0 -111
- data/lib/ppc/api/baidu/keyword.rb +0 -204
- data/lib/ppc/api/baidu/plan.rb +0 -68
- data/lib/ppc/api/baidu/report.rb +0 -143
- data/lib/ppc/api/qihu.rb +0 -107
- data/lib/ppc/api/qihu/account.rb +0 -86
- data/lib/ppc/api/qihu/creative.rb +0 -106
- data/lib/ppc/api/qihu/group.rb +0 -113
- data/lib/ppc/api/qihu/keyword.rb +0 -111
- data/lib/ppc/api/qihu/plan.rb +0 -64
- data/lib/ppc/api/qihu/report.rb +0 -159
- data/lib/ppc/api/shenma.rb +0 -64
- data/lib/ppc/api/shenma/report.rb +0 -135
- data/lib/ppc/api/sogou.rb +0 -122
- data/lib/ppc/api/sogou/account.rb +0 -42
- data/lib/ppc/api/sogou/creative.rb +0 -117
- data/lib/ppc/api/sogou/group.rb +0 -116
- data/lib/ppc/api/sogou/keyword.rb +0 -182
- data/lib/ppc/api/sogou/plan.rb +0 -66
- data/lib/ppc/api/sogou/report.rb +0 -129
- data/lib/ppc/ext.rb +0 -9
- data/lib/ppc/operation.rb +0 -196
- data/lib/ppc/operation/account.rb +0 -53
- data/lib/ppc/operation/creative.rb +0 -28
- data/lib/ppc/operation/group.rb +0 -59
- data/lib/ppc/operation/keyword.rb +0 -32
- data/lib/ppc/operation/plan.rb +0 -47
- data/lib/ppc/operation/report.rb +0 -19
- data/ppc.gemspec +0 -26
- data/spec/baidu/api_baidu_account_spec.rb +0 -15
- data/spec/baidu/api_baidu_creative_spec.rb +0 -67
- data/spec/baidu/api_baidu_group_spec.rb +0 -45
- data/spec/baidu/api_baidu_keyword_spec.rb +0 -61
- data/spec/baidu/api_baidu_plan_spec.rb +0 -43
- data/spec/baidu/api_baidu_report_spec.rb +0 -44
- data/spec/baidu/api_baidu_spec.rb +0 -55
- data/spec/operation/operation_baidu_report_spec.rb +0 -17
- data/spec/operation/operation_baidu_spec.rb +0 -78
- data/spec/operation/operation_qihu_report_spec.rb +0 -18
- data/spec/operation/operation_qihu_spec.rb +0 -51
- data/spec/operation/operation_sogou_report_spec.rb +0 -17
- data/spec/operation/operation_sogou_spec.rb +0 -51
- data/spec/operation/operation_spec_helper.rb +0 -51
- data/spec/qihu/api_qihu_account_spec.rb +0 -25
- data/spec/qihu/api_qihu_creative_spec.rb +0 -48
- data/spec/qihu/api_qihu_group_spec.rb +0 -40
- data/spec/qihu/api_qihu_keyword_spec.rb +0 -50
- data/spec/qihu/api_qihu_plan_spec.rb +0 -39
- data/spec/qihu/api_qihu_report_spec.rb +0 -54
- data/spec/sogou/api_sogou_account_spec.rb +0 -15
- data/spec/sogou/api_sogou_creative_spec.rb +0 -48
- data/spec/sogou/api_sogou_group_spec.rb +0 -45
- data/spec/sogou/api_sogou_keyword_spec.rb +0 -50
- data/spec/sogou/api_sogou_plan_spec.rb +0 -39
- data/spec/sogou/api_sogou_report_spec.rb +0 -51
- data/spec/spec_helper.rb +0 -134
data/lib/ppc/api/qihu/group.rb
DELETED
@@ -1,113 +0,0 @@
|
|
1
|
-
# -*- coding:utf-8 -*-
|
2
|
-
module PPC
|
3
|
-
module API
|
4
|
-
class Qihu
|
5
|
-
class Group < Qihu
|
6
|
-
Service = 'group'
|
7
|
-
|
8
|
-
@map = [
|
9
|
-
[:id, :id ],
|
10
|
-
[:plan_id, :campaignId],
|
11
|
-
[:status, :status ],
|
12
|
-
[:name, :name ],
|
13
|
-
[:price, :price ],
|
14
|
-
# negateive为json格式,make_type要定制
|
15
|
-
[:negative, :negativeWords ],
|
16
|
-
[:add_time, :addTime],
|
17
|
-
[:update_time, :updateTime]
|
18
|
-
]
|
19
|
-
|
20
|
-
# 再次封装提供all和ids
|
21
|
-
def self.ids( auth )
|
22
|
-
'''
|
23
|
-
接口与其他的相同,但是无论如何:succ均为true,不返回任何错误信息
|
24
|
-
因为是重复调用了search的接口,速度非常的慢,* 慎用 *
|
25
|
-
'''
|
26
|
-
plan_ids = ::PPC::API::Qihu::Plan::ids( auth )[:result]
|
27
|
-
plan_group_ids = []
|
28
|
-
|
29
|
-
plan_ids.each do |plan_id|
|
30
|
-
plan_group_id = {}
|
31
|
-
plan_group_id[:plan_id] = plan_id
|
32
|
-
plan_group_id[:group_ids] = search_id_by_plan_id( auth, plan_id )[:result]
|
33
|
-
plan_group_ids << plan_group_id
|
34
|
-
end
|
35
|
-
return { succ: true, failure:nil, result: plan_group_ids }
|
36
|
-
end
|
37
|
-
|
38
|
-
def self.all( auth )
|
39
|
-
'''
|
40
|
-
unimplemented due to ineffciency
|
41
|
-
'''
|
42
|
-
# unimplement
|
43
|
-
end
|
44
|
-
|
45
|
-
# 奇虎组服务不提供批量add,delete和update方法
|
46
|
-
def self.add( auth, group )
|
47
|
-
response = request( auth, Service, 'add', make_type( group )[0] )
|
48
|
-
# 保证接口一致性
|
49
|
-
process( response, 'id' ){ |x| [ { id:x.to_i } ] }
|
50
|
-
end
|
51
|
-
|
52
|
-
def self.update( auth, group )
|
53
|
-
response = request( auth, Service, 'update', make_type( group )[0] )
|
54
|
-
# 保证接口一致性
|
55
|
-
process( response, 'id' ){ |x|[ { id:x.to_i } ] }
|
56
|
-
end
|
57
|
-
|
58
|
-
def self.get( auth, ids )
|
59
|
-
ids = to_json_string( ids )
|
60
|
-
body = { 'idList' => ids }
|
61
|
-
response = request( auth, Service, 'getInfoByIdList', body )
|
62
|
-
process( response, 'groupList' ){ |x| reverse_type( x['item'] ) }
|
63
|
-
end
|
64
|
-
|
65
|
-
def self.delete( auth, id )
|
66
|
-
response = request( auth, Service, 'deleteById', { id: id} )
|
67
|
-
process( response, 'affectedRecords' ){ |x| x == '1' }
|
68
|
-
end
|
69
|
-
|
70
|
-
def self.search_id_by_plan_id( auth, id )
|
71
|
-
response = request( auth, Service, 'getIdListByCampaignId', { 'campaignId' => id.to_s })
|
72
|
-
#为了保持接口一致性,这里也是伪装成了百度的接口
|
73
|
-
process( response, 'groupIdList' ){
|
74
|
-
|x|
|
75
|
-
[ { plan_id:id, group_ids: to_id_list( x==nil ? nil: x['item'] ) } ]
|
76
|
-
}
|
77
|
-
end
|
78
|
-
|
79
|
-
# combine searchIdbyId and get to provide another method
|
80
|
-
def self.search_by_plan_id( auth, id )
|
81
|
-
group_ids = search_id_by_plan_id( auth, id )[:result][0][:group_ids]
|
82
|
-
response = get( auth, group_ids )
|
83
|
-
if response[:succ]
|
84
|
-
response[:result] = [ { plan_id:id, groups:response[:result]}]
|
85
|
-
end
|
86
|
-
return response
|
87
|
-
end
|
88
|
-
|
89
|
-
# customize make type to convert negative word
|
90
|
-
def self.make_type( params, map = @map)
|
91
|
-
'''
|
92
|
-
'''
|
93
|
-
params = [ params ] unless params.is_a? Array
|
94
|
-
|
95
|
-
types = []
|
96
|
-
params.each do |param|
|
97
|
-
type = {}
|
98
|
-
|
99
|
-
map.each do |key|
|
100
|
-
# next line transfer negative param to json
|
101
|
-
key[0]==:negative&¶m[:negative] ? value=param[:negative].to_json : value=param[key[0]]
|
102
|
-
type[ key[1] ] = value if value != nil
|
103
|
-
end
|
104
|
-
|
105
|
-
types << type
|
106
|
-
end
|
107
|
-
return types
|
108
|
-
end
|
109
|
-
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
data/lib/ppc/api/qihu/keyword.rb
DELETED
@@ -1,111 +0,0 @@
|
|
1
|
-
# -*- coding:utf-8 -*-
|
2
|
-
module PPC
|
3
|
-
module API
|
4
|
-
class Qihu
|
5
|
-
class Keyword< Qihu
|
6
|
-
Service = 'keyword'
|
7
|
-
|
8
|
-
@map = [
|
9
|
-
[:id, :id],
|
10
|
-
[:group_id, :groupId],
|
11
|
-
[:keyword, :word],
|
12
|
-
[:price, :price],
|
13
|
-
[:match_type, :matchType],
|
14
|
-
[:pc_destination, :destinationUrl],
|
15
|
-
[:status, :status]
|
16
|
-
]
|
17
|
-
|
18
|
-
@status_map = [
|
19
|
-
[:id,:id],
|
20
|
-
[:quality,:qualityScore],
|
21
|
-
[:status,:status]
|
22
|
-
]
|
23
|
-
|
24
|
-
def self.get( auth, ids )
|
25
|
-
ids = to_json_string( ids )
|
26
|
-
body = { 'idList' => ids }
|
27
|
-
response = request( auth, Service, 'getInfoByIdList', body )
|
28
|
-
process( response, 'keywordList'){ |x| reverse_type( x['item'] ) }
|
29
|
-
end
|
30
|
-
|
31
|
-
def self.add( auth, keywords )
|
32
|
-
keyword_types = make_type( keywords ).to_json
|
33
|
-
body = { 'keywords' => keyword_types}
|
34
|
-
response = request( auth, Service, 'add', body )
|
35
|
-
process( response, 'keywordIdList'){ |x| to_id_hash_list( x['item'] ) }
|
36
|
-
end
|
37
|
-
|
38
|
-
# helper function for self.add() method
|
39
|
-
private
|
40
|
-
def self.to_id_hash_list( str )
|
41
|
-
reuturn [] if str == nil
|
42
|
-
str = [str] unless str.is_a?Array
|
43
|
-
x= []
|
44
|
-
str.each{ |i| x << { id: i.to_i } }
|
45
|
-
return x
|
46
|
-
end
|
47
|
-
|
48
|
-
def self.update( auth, keywords )
|
49
|
-
keyword_types = make_type( keywords ).to_json
|
50
|
-
body = { 'keywords' => keyword_types}
|
51
|
-
response = request( auth, Service, 'update', body )
|
52
|
-
process( response, 'affectedRecords', 'failKeywordIds' ){ |x| x }
|
53
|
-
end
|
54
|
-
|
55
|
-
# 对update的再封装实现activate方法
|
56
|
-
def self.activate( auth, ids )
|
57
|
-
keywords = []
|
58
|
-
ids.each{ |id| keywords << { id: id, status:'enable'} }
|
59
|
-
update( auth, keywords )
|
60
|
-
end
|
61
|
-
|
62
|
-
def self.delete( auth, ids )
|
63
|
-
body = { 'idList' => to_json_string( ids ) }
|
64
|
-
response = request( auth, Service, 'deleteByIdList', body )
|
65
|
-
process( response, 'affectedRecords' ){ |x| x }
|
66
|
-
end
|
67
|
-
|
68
|
-
def self.status( auth, ids )
|
69
|
-
body = { idList: to_json_string( ids ) }
|
70
|
-
response = request( auth, Service, 'getStatusByIdList', body )
|
71
|
-
process( response, 'keywordList' ){ |x| reverse_type( x['item'], @status_map ) }
|
72
|
-
end
|
73
|
-
|
74
|
-
# quality 本质上和 status 在一个方法里面
|
75
|
-
def self.quality( auth, ids )
|
76
|
-
status( auth, ids)
|
77
|
-
end
|
78
|
-
|
79
|
-
def self.search_id_by_group_id( auth, id, status = nil, match_type = nil )
|
80
|
-
# 处理条件
|
81
|
-
body = {}
|
82
|
-
body['status'] = status if status
|
83
|
-
body['matchType'] = match_type if match_type
|
84
|
-
body['groupId'] = id
|
85
|
-
response = request( auth, Service, 'getIdListByGroupId', body )
|
86
|
-
# 伪装成百度接口
|
87
|
-
process( response, 'keywordIdList' ){
|
88
|
-
|x|
|
89
|
-
[ { group_id:id, keyword_ids:to_id_list( x==nil ? nil: x['item'] ) } ]
|
90
|
-
}
|
91
|
-
end
|
92
|
-
|
93
|
-
# combine search_id and get to provide another method
|
94
|
-
def self.search_by_group_id( auth, id )
|
95
|
-
keyword_ids = search_id_by_group_id( auth, id )[:result][0][:keyword_ids]
|
96
|
-
response = get( auth, keyword_ids )
|
97
|
-
if response[:succ]
|
98
|
-
# 伪装成百度接口
|
99
|
-
response[:result] = [ { group_id:id, keywords:response[:result] } ]
|
100
|
-
end
|
101
|
-
return response
|
102
|
-
end
|
103
|
-
|
104
|
-
def self.getChangedIdList
|
105
|
-
# unimplemented
|
106
|
-
end
|
107
|
-
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
data/lib/ppc/api/qihu/plan.rb
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
# -*- coding:utf-8 -*-
|
2
|
-
module PPC
|
3
|
-
module API
|
4
|
-
class Qihu
|
5
|
-
class Plan < Qihu
|
6
|
-
Service = 'campaign'
|
7
|
-
|
8
|
-
@map = [
|
9
|
-
[:id, :id],
|
10
|
-
[:name,:name],
|
11
|
-
[:budget, :budget],
|
12
|
-
[:region, :region],
|
13
|
-
[:schedule, :schedule],
|
14
|
-
[:startDate, :startDate],
|
15
|
-
[:endDate, :endDate ],
|
16
|
-
[:status,:status],
|
17
|
-
[:extend_ad_type,:extendAdType]
|
18
|
-
]
|
19
|
-
|
20
|
-
|
21
|
-
def self.get( auth, ids )
|
22
|
-
'''
|
23
|
-
:Type ids: ( Array of ) String or integer
|
24
|
-
'''
|
25
|
-
ids = to_json_string( ids )
|
26
|
-
body = { ' idList' => ids }
|
27
|
-
response = request( auth, Service, 'getInfoByIdList', body )
|
28
|
-
process( response, 'campaignList' ){ |x| reverse_type( x['item'] ) }
|
29
|
-
end
|
30
|
-
|
31
|
-
# move getCampaignId to plan module for operation call
|
32
|
-
def self.ids( auth )
|
33
|
-
response = request( auth, 'account', 'getCampaignIdList' )
|
34
|
-
process( response, 'campaignIdList' ){ |x| to_id_list( x['item'])}
|
35
|
-
end
|
36
|
-
|
37
|
-
# combine two original method to provice new method
|
38
|
-
def self.all( auth )
|
39
|
-
plan_ids = ids( auth )[:result]
|
40
|
-
get( auth, plan_ids )
|
41
|
-
end
|
42
|
-
|
43
|
-
# 奇虎计划API不提供批量服务
|
44
|
-
def self.add( auth, plan )
|
45
|
-
response = request( auth, Service, 'add', make_type( plan )[0])
|
46
|
-
# 这里将返回的简单int做一个array和hash的封装一保证接口和百度,搜狗的一致性
|
47
|
-
process( response, 'id' ){ |x| [ { id:x.to_i } ] }
|
48
|
-
end
|
49
|
-
|
50
|
-
def self.update( auth, plan )
|
51
|
-
response = request( auth, Service, 'update', make_type( plan )[0])
|
52
|
-
#同上,保证接口一致性
|
53
|
-
process( response, 'id' ){ |x| [ { id:x.to_i } ] }
|
54
|
-
end
|
55
|
-
|
56
|
-
def self.delete( auth, id )
|
57
|
-
response = request( auth, Service, 'deleteById', { id: id } )
|
58
|
-
process( response, 'affectedRecords' ){ |x| x == '1'? 'success' : 'fail' }
|
59
|
-
end
|
60
|
-
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
data/lib/ppc/api/qihu/report.rb
DELETED
@@ -1,159 +0,0 @@
|
|
1
|
-
# -*- coding:utf-8 -*-
|
2
|
-
require 'json'
|
3
|
-
|
4
|
-
module PPC
|
5
|
-
module API
|
6
|
-
class Qihu
|
7
|
-
class Report< Qihu
|
8
|
-
Service = 'report'
|
9
|
-
|
10
|
-
@map =[
|
11
|
-
[:queryword,:queryword],
|
12
|
-
[:plan_id,:campaignId],
|
13
|
-
[:creative_id,:creativeId],
|
14
|
-
[:keyword,:keyword],
|
15
|
-
[:views,:views],
|
16
|
-
[:clicks,:clicks],
|
17
|
-
[:startDate,:startDate],
|
18
|
-
[:endDate,:endDate],
|
19
|
-
[:date,:date],
|
20
|
-
[:keyword_id,:keywordId],
|
21
|
-
[:group_id,:groupId],
|
22
|
-
[:cost,:totalCost],
|
23
|
-
[:position,:avgPosition],
|
24
|
-
[:total_num,:totalNumber],
|
25
|
-
[:total_page,:totalPage]
|
26
|
-
]
|
27
|
-
|
28
|
-
###################
|
29
|
-
# API abstraction #
|
30
|
-
###################
|
31
|
-
def self.abstract( auth, type_name, method_name, key, param = nil, &func )
|
32
|
-
body = make_type( param )
|
33
|
-
response = request( auth, Service, method_name, body )
|
34
|
-
process( response, key ){ |x| func[ x ] }
|
35
|
-
end
|
36
|
-
|
37
|
-
type_list = ['keyword', 'query', 'creative', 'sublink']
|
38
|
-
type_list.each do |type|
|
39
|
-
# type
|
40
|
-
define_singleton_method type.to_sym do |auth, param|
|
41
|
-
abstract( auth, type, type, type+'List', param ){ |x| x['item']}
|
42
|
-
end
|
43
|
-
# typeCount
|
44
|
-
define_singleton_method (type+'_count').to_sym do |auth, param|
|
45
|
-
response = abstract( auth, type, type+'Count', '', param ){ |x| get_item(x) }
|
46
|
-
response[:result] = response[:result][0]
|
47
|
-
return response
|
48
|
-
end
|
49
|
-
# typeNow
|
50
|
-
define_singleton_method (type+'_now').to_sym do |auth, param|
|
51
|
-
abstract( auth, type, type+'Now', type+'List', param ){ |x| x['item']}
|
52
|
-
end
|
53
|
-
# typeNowCount
|
54
|
-
define_singleton_method (type+'_now_count').to_sym do |auth, param|
|
55
|
-
response = abstract( auth, type, type+'NowCount', '', param ){ |x| get_item(x) }
|
56
|
-
response[:result] = response[:result][0]
|
57
|
-
return response
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
############################
|
62
|
-
# Interfaces for operation #
|
63
|
-
############################
|
64
|
-
def self.keyword_report( auth, param, debug = false )
|
65
|
-
download_report(auth, 'keyword', param, debug )
|
66
|
-
end
|
67
|
-
|
68
|
-
def self.creative_report( auth, param, debug = false )
|
69
|
-
download_report(auth, 'creative', param, debug)
|
70
|
-
end
|
71
|
-
|
72
|
-
def self.download_report(auth, type, param, debug = false)
|
73
|
-
# deal_with time
|
74
|
-
now = Time.now.to_s[0...10]
|
75
|
-
is_now = now==parse_date(param[:startDate])
|
76
|
-
|
77
|
-
# get page num
|
78
|
-
if is_now
|
79
|
-
method = (type+'_now_count').to_sym
|
80
|
-
count = send(method, auth, param)[:result]
|
81
|
-
method = (type+'_now').to_sym
|
82
|
-
else
|
83
|
-
method = (type+'_count').to_sym
|
84
|
-
count = send(method, auth, param)[:result]
|
85
|
-
method = type.to_sym
|
86
|
-
end
|
87
|
-
|
88
|
-
report = []
|
89
|
-
count[:total_page].to_i.times do | page_i|
|
90
|
-
p "Start downloading #{page_i+1}th page, totally #{count[:total_page]} pages"
|
91
|
-
param[:page] = page_i +1
|
92
|
-
report_i = send(method, auth, param)[:result]
|
93
|
-
report += report_i
|
94
|
-
end
|
95
|
-
|
96
|
-
return report
|
97
|
-
end
|
98
|
-
|
99
|
-
###################
|
100
|
-
# Helper Function #
|
101
|
-
###################
|
102
|
-
# incase idlist == nil
|
103
|
-
private
|
104
|
-
def self.get_item( params )
|
105
|
-
return nil if params == nil
|
106
|
-
return reverse_type( params )
|
107
|
-
end
|
108
|
-
|
109
|
-
private
|
110
|
-
def self.make_type( param )
|
111
|
-
type = {}
|
112
|
-
# add option
|
113
|
-
type[:level] = param[:level] || 'account'
|
114
|
-
type[:page] = param[:page] || 1
|
115
|
-
# add ids
|
116
|
-
if param[:ids] != nil
|
117
|
-
ids = param[:ids]
|
118
|
-
ids = [ ids ] unless ids.is_a? Array
|
119
|
-
type[:IdList] = ids.to_json
|
120
|
-
end
|
121
|
-
# add date
|
122
|
-
if param[:startDate]==nil || param[:endDate]==nil
|
123
|
-
type[:startDate], type[:endDate] = get_date()
|
124
|
-
else
|
125
|
-
type[:startDate] = parse_date( param[:startDate] )
|
126
|
-
type[:endDate] = parse_date( param[:endDate] )
|
127
|
-
end
|
128
|
-
|
129
|
-
return type
|
130
|
-
end
|
131
|
-
|
132
|
-
private
|
133
|
-
def self.get_date()
|
134
|
-
endDate = Time.now.to_s[0,10]
|
135
|
-
startDate = (Time.now - 24*3600).to_s[0,10]
|
136
|
-
return startDate,endDate
|
137
|
-
end
|
138
|
-
|
139
|
-
private
|
140
|
-
def self.parse_date( date )
|
141
|
-
"""
|
142
|
-
Cast string to time:
|
143
|
-
'YYYYMMDD' => Time
|
144
|
-
"""
|
145
|
-
if date
|
146
|
-
y = date[0..3]
|
147
|
-
m = date[4..5]
|
148
|
-
d = date[6..7]
|
149
|
-
date = Time.new( y, m, d )
|
150
|
-
else
|
151
|
-
date = (Time.now - 24*3600)
|
152
|
-
end
|
153
|
-
date.to_s[0,10]
|
154
|
-
end
|
155
|
-
|
156
|
-
end # Report
|
157
|
-
end # Qihu
|
158
|
-
end # API
|
159
|
-
end # PPC
|