sogou-search-api 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e5c716c3f0a2b1c807eb08265f4b9ee700ae33d7
4
+ data.tar.gz: c66b6cd0d0e800170161a24b8ebde867ce54fce7
5
+ SHA512:
6
+ metadata.gz: 627e5d14ebd0314ecb7330761522375dff5a54fa20152d0177493120c44235ddcea00841f76b5285912a2e960afc5dfcffd49f3c2a112b12081f87fd5b1d6214
7
+ data.tar.gz: a944be7071287c114fc205fb730d55c8e763fd7ef57e005e94e0c32c279da5a5b75fb6d09bba2620ff1a3fd9434cb6b3c5b1419d448348b97a1fa747df6dfc54
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
13
+ .DS_Store
14
+
15
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sogou-search-api.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018-present Forward3D
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,8 @@
1
+ # Sogou Search API
2
+
3
+ A Client GEM for [Sogou Search API](http://apihome.sogou.com/document/ss/doc1-1.jsp)
4
+
5
+ ## Alpha
6
+
7
+ This library is in Alpha. We will make an effort to support the library, but we reserve the right to make incompatible
8
+ changes when necessary.
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "sogou/search/api"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,22 @@
1
+ require 'sogou/search/api/auth'
2
+ require 'sogou/search/api/service/account'
3
+ require 'sogou/search/api/service/plan'
4
+
5
+ #
6
+ # Set your Sogou api credentials to ENVs
7
+ #
8
+ # ENV['SOGOU_API_TOKEN'] = 'xxxx'
9
+ # ENV['SOGOU_USERNAME'] = 'xxxx'
10
+ # ENV['SOGOU_PASSWORD'] = 'xxxx'
11
+
12
+ include Sogou::Search::Api
13
+
14
+ account = Service::Account.new
15
+ account.authorization = Auth.get_application_default
16
+ account.get_account_info(convert_regions_to_string: true) do |result, err|
17
+ if err != nil
18
+ p err
19
+ else
20
+ p result
21
+ end
22
+ end
@@ -0,0 +1,40 @@
1
+ require 'sogou/search/api/auth'
2
+ require 'sogou/search/api/service/plan'
3
+ require 'sogou/search/api/service/promotion_group'
4
+ require 'sogou/search/api/service/keyword'
5
+
6
+ #
7
+ # Set your Sogou api credentials to ENVs
8
+ #
9
+ # ENV['SOGOU_API_TOKEN'] = 'xxxx'
10
+ # ENV['SOGOU_USERNAME'] = 'xxxx'
11
+ # ENV['SOGOU_PASSWORD'] = 'xxxx'
12
+
13
+ include Sogou::Search::Api
14
+
15
+ plan = Service::Plan.new
16
+ plan.authorization = Auth.get_application_default
17
+ plan_ids = plan.get_all_cpc_plan_id.slice(0, 2)
18
+
19
+ group = Service::PromotionGroup.new
20
+ group.authorization = Auth.get_application_default
21
+ group_ids = group.get_cpc_grp_id_by_cpc_plan_id(plan_ids).
22
+ map { |id| id['cpc_grp_ids'] }.flatten.slice(0, 2)
23
+
24
+ keyword = Service::Keyword.new
25
+ keyword.authorization = Auth.get_application_default
26
+ keyword.get_cpc_by_cpc_grp_id(group_ids) do |result, err|
27
+ if err != nil
28
+ p err
29
+ else
30
+ p result
31
+ end
32
+ end
33
+
34
+ keyword.get_cpc_id_by_cpc_grp_id(group_ids) do |result, err|
35
+ if err != nil
36
+ p err
37
+ else
38
+ p result
39
+ end
40
+ end
@@ -0,0 +1,29 @@
1
+ require 'sogou/search/api/auth'
2
+ require 'sogou/search/api/service/plan'
3
+
4
+ #
5
+ # Set your Sogou api credentials to ENVs
6
+ #
7
+ # ENV['SOGOU_API_TOKEN'] = 'xxxx'
8
+ # ENV['SOGOU_USERNAME'] = 'xxxx'
9
+ # ENV['SOGOU_PASSWORD'] = 'xxxx'
10
+
11
+ include Sogou::Search::Api
12
+
13
+ plan = Service::Plan.new
14
+ plan.authorization = Auth.get_application_default
15
+ plan.get_all_cpc_plan(convert_regions_to_string: true) do |result, err|
16
+ if err != nil
17
+ p err
18
+ else
19
+ p result
20
+ end
21
+ end
22
+
23
+ plan.get_all_cpc_plan_id do |result, err|
24
+ if err != nil
25
+ p err
26
+ else
27
+ p result
28
+ end
29
+ end
@@ -0,0 +1,43 @@
1
+ require 'sogou/search/api/auth'
2
+ require 'sogou/search/api/service/plan'
3
+ require 'sogou/search/api/service/promotion_group'
4
+
5
+ #
6
+ # Set your Sogou api credentials to ENVs
7
+ #
8
+ # ENV['SOGOU_API_TOKEN'] = 'xxxx'
9
+ # ENV['SOGOU_USERNAME'] = 'xxxx'
10
+ # ENV['SOGOU_PASSWORD'] = 'xxxx'
11
+
12
+ include Sogou::Search::Api
13
+
14
+ plan = Service::Plan.new
15
+ plan.authorization = Auth.get_application_default
16
+ plan_ids = plan.get_all_cpc_plan_id.slice(0, 2)
17
+
18
+ group = Service::PromotionGroup.new
19
+ group.authorization = Auth.get_application_default
20
+ group.get_cpc_grp_by_cpc_plan_id(plan_ids) do |result, err|
21
+ if err != nil
22
+ p err
23
+ else
24
+ p result
25
+ end
26
+ end
27
+
28
+ group.get_cpc_grp_id_by_cpc_plan_id(plan_ids) do |result, err|
29
+ if err != nil
30
+ p err
31
+ else
32
+ p result
33
+ end
34
+ end
35
+
36
+ # Error
37
+ group.get_cpc_grp_by_cpc_plan_id([1, 2]) do |result, err|
38
+ if err != nil
39
+ p err
40
+ else
41
+ p result
42
+ end
43
+ end
@@ -0,0 +1,37 @@
1
+ require 'sogou/search/api/auth'
2
+ require 'sogou/search/api/service/report'
3
+
4
+ #
5
+ # Set your Sogou api credentials to ENVs
6
+ #
7
+ # ENV['SOGOU_API_TOKEN'] = 'xxxx'
8
+ # ENV['SOGOU_USERNAME'] = 'xxxx'
9
+ # ENV['SOGOU_PASSWORD'] = 'xxxx'
10
+
11
+ include Sogou::Search::Api
12
+
13
+ report = Service::Report.new
14
+ report.authorization = Auth.get_application_default
15
+ report_id = report.get_report_id(
16
+ '2018-02-20T00:00:00',
17
+ '2018-02-20T23:59:59',
18
+ 1,
19
+ ['cost', 'cpc', 'click', 'ctr', 'position']
20
+ )
21
+
22
+ state = '0'
23
+ max_try = 10
24
+ try = 0
25
+
26
+ while state != '1' && try < 10
27
+ sleep(5)
28
+ state = report.get_report_state(report_id)
29
+ try += 1
30
+ end
31
+
32
+ if state == '1'
33
+ path = report.get_report_path(report_id)
34
+ p path
35
+ else
36
+ puts 'Timed out'
37
+ end
@@ -0,0 +1,35 @@
1
+ require 'sogou/search/api/version'
2
+ require 'logger'
3
+
4
+ module Sogou
5
+ module Search
6
+ module Api
7
+ ROOT = File.expand_path('..', File.dirname(__dir__))
8
+
9
+ def self.logger
10
+ @logger ||= (rails_logger || default_logger)
11
+ end
12
+
13
+ class << self
14
+ attr_writer :logger
15
+ end
16
+
17
+ private
18
+
19
+ def self.default_logger
20
+ logger = Logger.new(STDOUT)
21
+ logger.level = Logger::WARN
22
+ logger
23
+ end
24
+
25
+ def self.rails_logger
26
+ if defined?(::Rails) && ::Rails.respond_to?(:logger) &&
27
+ !::Rails.logger.nil?
28
+ ::Rails.logger
29
+ else
30
+ nil
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,54 @@
1
+ module Sogou
2
+ module Search
3
+ module Api
4
+ module Auth
5
+ class V1AcccountCredentials
6
+ USERNAME_HEADER = 'v1:username'.freeze
7
+ PASSWORD_HEADER = 'v1:password'.freeze
8
+ API_TOKEN_HEADER = 'v1:token'.freeze
9
+ AUTH_HEADER = 'v1:AuthHeader'.freeze
10
+
11
+ attr_reader :api_token
12
+ attr_reader :username
13
+ attr_reader :password
14
+
15
+ def initialize(api_token, username, password)
16
+ @api_token = api_token
17
+ @username = username
18
+ @password = password
19
+ end
20
+
21
+ def apply(hash)
22
+ hash ||= {}
23
+ hash[AUTH_HEADER] = {
24
+ USERNAME_HEADER => username,
25
+ PASSWORD_HEADER => password,
26
+ API_TOKEN_HEADER => api_token
27
+ }
28
+ hash
29
+ end
30
+ end
31
+
32
+ class DefaultCredentials
33
+ API_TOKEN_ENV_VAR = 'SOGOU_API_TOKEN'.freeze
34
+ USERNAME_ENV_VAR = 'SOGOU_USERNAME'.freeze
35
+ PASSWORD_ENV_VAR = 'SOGOU_PASSWORD'.freeze
36
+
37
+ def self.from_env
38
+ V1AcccountCredentials.new(
39
+ ENV[API_TOKEN_ENV_VAR],
40
+ ENV[USERNAME_ENV_VAR],
41
+ ENV[PASSWORD_ENV_VAR]
42
+ )
43
+ end
44
+ end
45
+
46
+ def get_application_default
47
+ DefaultCredentials.from_env
48
+ end
49
+
50
+ module_function :get_application_default
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,114 @@
1
+ require_relative '../errors'
2
+ require_relative 'logging'
3
+ require_relative 'regions'
4
+
5
+ module Sogou
6
+ module Search
7
+ module Api
8
+ module Core
9
+ class ApiCommand
10
+ include Logging
11
+ include Regions
12
+
13
+ attr_accessor :operation
14
+ attr_accessor :options
15
+ attr_accessor :params
16
+
17
+ def initialize(operation)
18
+ @operation = operation
19
+ @params = {}
20
+ @options = {}
21
+ end
22
+
23
+ def execute(client, &block)
24
+ logger.debug("Executing SOAP #{operation}")
25
+
26
+ resp = client.call(@operation, message: @params)
27
+ result = process_response(resp)
28
+
29
+ logger.debug("Success - #{result}")
30
+ success(result, &block)
31
+ rescue => e
32
+ logger.debug("Error - #{e.inspect}")
33
+ error(e, &block)
34
+ end
35
+
36
+ def process_response(response)
37
+ check_status(response)
38
+ decode_response_body(response.body)
39
+ end
40
+
41
+ def check_status(response)
42
+ logger.debug("Response Header - #{response.header}")
43
+ res_header = response.header['res_header']
44
+ check_error_code(res_header['failures']) if res_header['desc'] != 'success'
45
+ end
46
+
47
+ def decode_response_body(body)
48
+ result = body["#{@operation}_response"]
49
+ if result
50
+ result = result.is_a?(Hash) ? result.values[0] : result
51
+ result = convert_regions_to_string(result) if options[:convert_regions_to_string]
52
+ result
53
+ end
54
+ end
55
+
56
+ #
57
+ # More error codes and descriptions can be found here
58
+ # http://apihome.sogou.com/document/ss/doc11.jsp
59
+ #
60
+ def check_error_code(header, raise_error = true)
61
+ res_header = header.is_a?(Array) ? header[0] : header
62
+ error_klass = case res_header['code'].to_i
63
+ when 6 # Invalid username
64
+ InvalidUserNameError
65
+ when 8 # Wrong password
66
+ WrongPasswordError
67
+ when 10 # Token is invalid
68
+ InvalidTokenError
69
+ when 18 # Insufficient quotas
70
+ RateLimitError
71
+ when 1000011 # Plan ID does not exist
72
+ PlanIDNotExistError
73
+ when 1000012 # Promotion group ID does not exist
74
+ PromotionGroupIDNotExistError
75
+ when 1000013 # Keyword ID does not exist
76
+ KeywordIDNotExistError
77
+ else
78
+ UnknownError
79
+ end
80
+
81
+ exception = error_klass.new(
82
+ res_header.fetch('message', 'Unknown error'),
83
+ code: res_header['code'],
84
+ header: header
85
+ )
86
+ raise_error ? (raise exception) : exception
87
+ end
88
+
89
+ private
90
+
91
+ def success(result)
92
+ yield(result, nil) if block_given?
93
+ result
94
+ end
95
+
96
+ def error(err)
97
+ if err.is_a?(Net::ReadTimeout) || err.is_a?(SocketError)
98
+ err = TransmissionError.new(err)
99
+ end
100
+
101
+ if block_given?
102
+ if err.respond_to?(:header) && err.header.is_a?(Array)
103
+ err = err.header.map { |h| check_error_code(h, false) }
104
+ end
105
+ yield(nil, err)
106
+ else
107
+ raise err
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end