google_web_translate 0.2.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 4fa88abae6fc3035a666db53549211dd084bbaaf
4
- data.tar.gz: 4942b2dd7b155f4507d8fd1b2c902c7e66074e98
2
+ SHA256:
3
+ metadata.gz: 7ffd5385d2f29f6faa1034ea2c9c0f458b063b7aa7b769789352727027e3167d
4
+ data.tar.gz: 3809d0162a684d6d452a0b0a83a07fb5fa36ecfbbf9f3967768aa457ffb6a421
5
5
  SHA512:
6
- metadata.gz: 857468dc26b8538e2be64454b1b1db9dc65ada47a53d63766c351e813ff9a5010e1759333aa0a80b194faae9adf26b895ef69aaf63c524398467016f2a04e394
7
- data.tar.gz: e37080f63adfbf5e0464b2e9f8340f7b22160e25ba36b736dd6e16404fb13e92359f80f4b9e6a3485ea1c9a1b4176dd7dc55f0360949637aae210f6a552b9287
6
+ metadata.gz: f901517261b1887923faaaa7ceaf8ea418bab7e7e71cda5b506e947d810bdd51790c44b81f15c1fc5e760f4fff954ef71a93bb5aaca273dd4e4fa0c46ffc1202
7
+ data.tar.gz: d9fd55c8cf55eede4671fda0d228bf89022a5babc418f8f9891afa1ac9844b27e460c437a1040ed46a7ce946b3165f3b657e5fa6b1b58132dde2f22dc1b90073
data/Gemfile CHANGED
@@ -1,24 +1,24 @@
1
- source 'https://rubygems.org'
2
-
3
- git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
-
5
- def gem_installed?(args)
6
- name, *version = *args
7
- dependency = Gem::Dependency.new(name, *version)
8
- specs = dependency.matching_specs
9
- specs && !specs.empty?
10
- end
11
-
12
- def optional_gem(*args)
13
- gem(*args) if gem_installed?(args)
14
- end
15
-
16
- # database adapters
17
- optional_gem 'therubyracer', platform: :ruby
18
- optional_gem 'therubyrhino', platform: :jruby
19
-
20
- # optional c extensions
21
- optional_gem 'concurrent-ruby-ext', platform: :ruby
22
-
23
- # Specify your gem's dependencies in google-web-translate.gemspec
24
- gemspec
1
+ source 'https://rubygems.org'
2
+
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ def gem_installed?(args)
6
+ name, *version = *args
7
+ dependency = Gem::Dependency.new(name, *version)
8
+ specs = dependency.matching_specs
9
+ specs && !specs.empty?
10
+ end
11
+
12
+ def optional_gem(*args)
13
+ gem(*args) if gem_installed?(args)
14
+ end
15
+
16
+ # database adapters
17
+ optional_gem 'therubyracer', platform: :ruby
18
+ optional_gem 'therubyrhino', platform: :jruby
19
+
20
+ # optional c extensions
21
+ optional_gem 'concurrent-ruby-ext', platform: :ruby
22
+
23
+ # Specify your gem's dependencies in google-web-translate.gemspec
24
+ gemspec
@@ -1,31 +1,31 @@
1
-
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'google_web_translate/version'
5
-
6
- Gem::Specification.new do |spec|
7
- spec.name = 'google_web_translate'
8
- spec.version = GoogleWebTranslate::VERSION
9
- spec.authors = ['Andrew']
10
- spec.email = ['sobakasu@gmail.com']
11
-
12
- spec.summary = 'Text translation using the google web interface'
13
- spec.homepage = 'https://github.com/sobakasu/google_web_translate'
14
- spec.license = 'MIT'
15
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
16
- f.match(%r{^(test|spec|features)/})
17
- end
18
- spec.bindir = 'bin'
19
- spec.executables = %w[google_web_translate]
20
- spec.require_paths = ['lib']
21
-
22
- spec.add_development_dependency 'bundler', '~> 1.16'
23
- spec.add_development_dependency 'rake', '~> 10.0'
24
- spec.add_development_dependency 'rspec', '~> 3.0'
25
- spec.add_development_dependency 'simplecov'
26
- spec.add_development_dependency 'webmock'
27
-
28
- spec.add_dependency 'concurrent-ruby'
29
- spec.add_dependency 'execjs'
30
- spec.add_dependency 'thor'
31
- end
1
+
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'google_web_translate/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'google_web_translate'
8
+ spec.version = GoogleWebTranslate::VERSION
9
+ spec.authors = ['Andrew']
10
+ spec.email = ['sobakasu@gmail.com']
11
+
12
+ spec.summary = 'Text translation using the google web interface'
13
+ spec.homepage = 'https://github.com/sobakasu/google_web_translate'
14
+ spec.license = 'MIT'
15
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
16
+ f.match(%r{^(test|spec|features)/})
17
+ end
18
+ spec.bindir = 'bin'
19
+ spec.executables = %w[google_web_translate]
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_development_dependency 'bundler', '~> 1.16'
23
+ spec.add_development_dependency 'rake', '~> 10.0'
24
+ spec.add_development_dependency 'rspec', '~> 3.0'
25
+ spec.add_development_dependency 'simplecov'
26
+ spec.add_development_dependency 'webmock'
27
+
28
+ spec.add_dependency 'concurrent-ruby'
29
+ spec.add_dependency 'execjs'
30
+ spec.add_dependency 'thor'
31
+ end
@@ -1,6 +1,7 @@
1
- require 'google_web_translate/version.rb'
2
- require 'google_web_translate/server_list.rb'
3
- require 'google_web_translate/string_escaping.rb'
4
- require 'google_web_translate/http_client.rb'
5
- require 'google_web_translate/result.rb'
6
- require 'google_web_translate/api.rb'
1
+ require 'google_web_translate/version.rb'
2
+ require 'google_web_translate/server.rb'
3
+ require 'google_web_translate/server_list.rb'
4
+ require 'google_web_translate/string_escaping.rb'
5
+ require 'google_web_translate/http_client.rb'
6
+ require 'google_web_translate/result.rb'
7
+ require 'google_web_translate/api.rb'
@@ -1,142 +1,151 @@
1
- require 'execjs'
2
- require 'json'
3
-
4
- module GoogleWebTranslate
5
- # interface to the google web translation api
6
- class API
7
- def initialize(options = {})
8
- @dt = options[:dt] || DEFAULT_DT
9
- @token_ttl = options[:token_ttl] || DEFAULT_TOKEN_TTL
10
- @debug = options[:debug]
11
- @http_client = options[:http_client] || HTTPClient.new(options)
12
- @rate_limit = options[:rate_limit] || DEFAULT_RATE_LIMIT
13
- end
14
-
15
- def translate(string, from, to)
16
- data = fetch_translation(string, from, to)
17
- Result.new(data)
18
- end
19
-
20
- def languages
21
- @languages ||= begin
22
- html = fetch_main
23
- html.scan(/\['(\w{2})','(\w{2})'\]/).flatten.uniq.sort
24
- end
25
- end
26
-
27
- private
28
-
29
- URL_MAIN = 'https://translate.google.com'.freeze
30
- TRANSLATE_PATH = '/translate_a/single'.freeze
31
- DEFAULT_DT = %w[at bd ex ld md qca rw rm ss t].freeze
32
- DEFAULT_TOKEN_TTL = 3600
33
- DEFAULT_RATE_LIMIT = 5
34
-
35
- def fetch_translation(string, from, to)
36
- server = ServerList.next_server(@rate_limit)
37
- json = fetch_url_body(translate_url(server, string, from, to))
38
- # File.write("response.json", json) if debug?
39
- debug("response: #{json}")
40
- JSON.parse(json)
41
- end
42
-
43
- def fetch_url_response(url)
44
- @http_client.get(url.to_s)
45
- end
46
-
47
- def fetch_url_body(url)
48
- uri = URI.parse(url)
49
- uri = URI.join(URL_MAIN, url) if uri.relative?
50
- debug("fetch #{uri}")
51
- response = fetch_url_response(uri)
52
- response.body
53
- end
54
-
55
- def valid_token?
56
- @token_updated_at && Time.now - @token_updated_at < @token_ttl
57
- end
58
-
59
- def fetch_main(options = {})
60
- @html = nil if options[:no_cache]
61
- @html ||= fetch_url_body(URL_MAIN)
62
- end
63
-
64
- def fetch_desktop_module(html)
65
- html =~ /([^="]*desktop_module_main.js)/
66
- url = Regexp.last_match(1)
67
- raise 'unable to find desktop module' unless url
68
- fetch_url_body(url)
69
- end
70
-
71
- def munge_module(js)
72
- js.gsub(/((?:var\s+)?\w+\s*=\s*\w+\.createElement.*?;)/) do |_i|
73
- 'return "";'
74
- end
75
- end
76
-
77
- def compile_js(html)
78
- desktop_module_js = munge_module(fetch_desktop_module(html))
79
- window_js = File.read(File.join(__dir__, '..', 'js', 'window.js'))
80
- js = window_js + desktop_module_js
81
- # File.write('generated.js', js) if debug?
82
- ExecJS.compile(js)
83
- end
84
-
85
- def update_token
86
- # download main page
87
- html = fetch_main(no_cache: true)
88
- # extract tkk from html
89
- @tkk = extract_tkk(html)
90
- # compile desktop module javascript
91
- @js_context = compile_js(html)
92
- @token_updated_at = Time.now
93
- end
94
-
95
- def tk(string)
96
- update_token unless valid_token?
97
- @js_context.call('setWindowProperty', 'TKK', @tkk)
98
- # tk = @js_context.call("wq", string)
99
- tk = @js_context.call('generateToken', string, @tkk)
100
- (tk.split('=') || [])[1]
101
- end
102
-
103
- def tk_js
104
- File.read(File.join(__dir__, 'google_web.js'))
105
- end
106
-
107
- def extract_tkk(html)
108
- raise 'TKK not found' unless html =~ /TKK=eval\('(.*?)'\);/
109
- tkk_code = Regexp.last_match(1)
110
- # tkk_code = Translatomatic::StringEscaping.unescape(tkk_code)
111
- tkk_code = StringEscaping.unescape(tkk_code)
112
- debug("tkk code unescaped: #{tkk_code}")
113
- tkk = ExecJS.eval(tkk_code)
114
- # tkk = context.call(nil)
115
- debug("evaluated tkk: #{tkk}")
116
- tkk
117
- end
118
-
119
- def translate_url(server, string, from, to)
120
- tk = tk(string)
121
- debug("tk: #{tk}")
122
- query = {
123
- sl: from, tl: to, ie: 'UTF-8', oe: 'UTF-8',
124
- q: string, dt: @dt, tk: tk,
125
- # not sure what these are for
126
- client: 't', hl: 'en', otf: 1, ssel: 4, tsel: 6, kc: 5
127
- }
128
- url = "https://#{server.host}" + TRANSLATE_PATH
129
- uri = URI.parse(url)
130
- uri.query = URI.encode_www_form(query)
131
- uri.to_s
132
- end
133
-
134
- def debug(msg)
135
- puts msg if debug?
136
- end
137
-
138
- def debug?
139
- @debug
140
- end
141
- end
142
- end
1
+ require 'execjs'
2
+ require 'json'
3
+
4
+ module GoogleWebTranslate
5
+ # interface to the google web translation api
6
+ class API
7
+ def initialize(options = {})
8
+ @dt = options[:dt] || DEFAULT_DT
9
+ @token_ttl = options[:token_ttl] || DEFAULT_TOKEN_TTL
10
+ @debug = options[:debug]
11
+ @http_client = options[:http_client] || HTTPClient.new(options)
12
+ @rate_limit = options[:rate_limit] || DEFAULT_RATE_LIMIT
13
+ end
14
+
15
+ def translate(string, from, to)
16
+ data = fetch_translation(string, from, to)
17
+ Result.new(data)
18
+ end
19
+
20
+ def languages
21
+ @languages ||= begin
22
+ html = fetch_main
23
+ html.scan(/\['(\w{2})','(\w{2})'\]/).flatten.uniq.sort
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ URL_MAIN = 'https://translate.google.com'.freeze
30
+ TRANSLATE_PATH = '/translate_a/single'.freeze
31
+ DEFAULT_DT = %w[at bd ex ld md qca rw rm ss t].freeze
32
+ DEFAULT_TOKEN_TTL = 3600
33
+ DEFAULT_RATE_LIMIT = 5
34
+
35
+ def fetch_translation(string, from, to)
36
+ debug('getting next server')
37
+ server = ServerList.next_server(@rate_limit)
38
+ debug("using server #{server}")
39
+ json = fetch_url_body(translate_url(server, string, from, to))
40
+ # File.write("response.json", json) if debug?
41
+ debug("response: #{json}")
42
+ JSON.parse(json)
43
+ end
44
+
45
+ def fetch_url_response(url)
46
+ @http_client.get(url.to_s)
47
+ end
48
+
49
+ def fetch_url_body(url)
50
+ uri = URI.parse(url)
51
+ uri = URI.join(URL_MAIN, url) if uri.relative?
52
+ debug("fetch #{uri}")
53
+ response = fetch_url_response(uri)
54
+ response.body
55
+ end
56
+
57
+ def valid_token?
58
+ @token_updated_at && Time.now - @token_updated_at < @token_ttl
59
+ end
60
+
61
+ def fetch_main(options = {})
62
+ @html = nil if options[:no_cache]
63
+ @html ||= fetch_url_body(URL_MAIN)
64
+ end
65
+
66
+ def fetch_desktop_module(html)
67
+ html =~ /([^="]*desktop_module_main.js)/
68
+ url = Regexp.last_match(1)
69
+ raise 'unable to find desktop module' unless url
70
+ fetch_url_body(url)
71
+ end
72
+
73
+ def munge_module(js)
74
+ js.gsub(/((?:var\s+)?\w+\s*=\s*\w+\.createElement.*?;)/) do |_i|
75
+ 'return "";'
76
+ end
77
+ end
78
+
79
+ def compile_js(html)
80
+ desktop_module_js = munge_module(fetch_desktop_module(html))
81
+ window_js = File.read(File.join(__dir__, '..', 'js', 'window.js'))
82
+ js = window_js + desktop_module_js
83
+ # File.write('generated.js', js) if debug?
84
+ @tk_function = detect_tk_function(desktop_module_js)
85
+ debug("detected tk function: #{@tk_function}")
86
+ ExecJS.compile(js)
87
+ end
88
+
89
+ def detect_tk_function(js)
90
+ js =~ /translate_tts.*,\s*(\w+)\(.*\)/
91
+ Regexp.last_match(1) || 'vq'
92
+ end
93
+
94
+ def update_token
95
+ # download main page
96
+ html = fetch_main(no_cache: true)
97
+ # extract tkk from html
98
+ @tkk = extract_tkk(html)
99
+ # compile desktop module javascript
100
+ @js_context = compile_js(html)
101
+ @token_updated_at = Time.now
102
+ end
103
+
104
+ def tk(string)
105
+ update_token unless valid_token?
106
+ @js_context.call('setWindowProperty', 'TKK', @tkk)
107
+ # tk = @js_context.call("wq", string)
108
+ tk = @js_context.call(@tk_function, string)
109
+ (tk.split('=') || [])[1]
110
+ end
111
+
112
+ def tk_js
113
+ File.read(File.join(__dir__, 'google_web.js'))
114
+ end
115
+
116
+ def extract_tkk(html)
117
+ raise 'TKK not found' unless html =~ /TKK=eval\('(.*?)'\);/
118
+ tkk_code = Regexp.last_match(1)
119
+ # tkk_code = Translatomatic::StringEscaping.unescape(tkk_code)
120
+ tkk_code = StringEscaping.unescape(tkk_code)
121
+ debug("tkk code unescaped: #{tkk_code}")
122
+ tkk = ExecJS.eval(tkk_code)
123
+ # tkk = context.call(nil)
124
+ debug("evaluated tkk: #{tkk}")
125
+ tkk
126
+ end
127
+
128
+ def translate_url(server, string, from, to)
129
+ tk = tk(string)
130
+ debug("tk: #{tk}")
131
+ query = {
132
+ sl: from, tl: to, ie: 'UTF-8', oe: 'UTF-8',
133
+ q: string, dt: @dt, tk: tk,
134
+ # not sure what these are for
135
+ client: 't', hl: 'en', otf: 1, ssel: 4, tsel: 6, kc: 5
136
+ }
137
+ url = "https://#{server.host}" + TRANSLATE_PATH
138
+ uri = URI.parse(url)
139
+ uri.query = URI.encode_www_form(query)
140
+ uri.to_s
141
+ end
142
+
143
+ def debug(msg)
144
+ puts msg if debug?
145
+ end
146
+
147
+ def debug?
148
+ @debug
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,13 @@
1
+ module GoogleWebTranslate
2
+ # @private
3
+ SERVER_ATTRIBUTES = %i[host ip resolved_at last_used_at
4
+ counter available].freeze
5
+
6
+ Server = Struct.new(*SERVER_ATTRIBUTES) do
7
+ def to_json(*args)
8
+ result = {}
9
+ each_pair { |key, value| result[key] = value }
10
+ result.to_json(args)
11
+ end
12
+ end
13
+ end
@@ -1,146 +1,135 @@
1
- require 'concurrent'
2
- require 'resolv'
3
- require 'json'
4
-
5
- module GoogleWebTranslate
6
- # @private
7
- SERVER_ATTRIBUTES = %i[host ip resolved_at last_used_at
8
- counter available].freeze
9
-
10
- Server = Struct.new(*SERVER_ATTRIBUTES) do
11
- def to_json(*args)
12
- result = {}
13
- each_pair { |key, value| result[key] = value }
14
- result.to_json(args)
15
- end
16
- end
17
-
18
- class ServerList
19
- class << self
20
- def servers
21
- update_servers if @servers.nil?
22
- @servers.dup
23
- end
24
-
25
- def next_server(rate_limit = nil)
26
- @mutex ||= Mutex.new
27
- @mutex.synchronize do
28
- @counter ||= 0
29
- @counter += 1
30
-
31
- list = servers.sort_by { |i| i.counter || 0 }
32
- server = list[0]
33
- server.counter = @counter
34
- sleep(rate_limit_delay(server, rate_limit))
35
- server.last_used_at = Time.now
36
- server
37
- end
38
- end
39
-
40
- private
41
-
42
- MAX_TTL = 86_400
43
-
44
- def rate_limit_delay(server, rate_limit)
45
- return 0 unless rate_limit && server.last_used_at
46
- delay = rate_limit - (Time.now - server.last_used_at)
47
- delay < 0 || ENV['TEST'] ? 0 : delay
48
- end
49
-
50
- def update_servers
51
- server_list = read_server_data
52
- pool = Concurrent::CachedThreadPool.new
53
- # puts "updating #{server_list.length} servers"
54
- server_list.each do |server|
55
- pool.post { update_server(server) }
56
- end
57
-
58
- pool.shutdown
59
- pool.wait_for_termination
60
- @servers = unique_servers(server_list)
61
- # puts "#{@servers.length} unique servers found"
62
- save_server_data(server_list)
63
- end
64
-
65
- def update_server(server)
66
- now = Time.now.to_i
67
- if server.resolved_at.nil? ||
68
- now - server.resolved_at > MAX_TTL || !server.available
69
- server.resolved_at = now
70
- server.ip = resolve_ip(server.host)
71
- end
72
- server.available = true
73
- rescue Resolv::ResolvError
74
- # puts "server #{server.host} is unavailable: #{e}"
75
- server.available = false
76
- end
77
-
78
- def data_dir
79
- File.join(__dir__, '..', '..', 'data')
80
- end
81
-
82
- def server_data_path
83
- File.join(data_dir, 'server_data.txt')
84
- end
85
-
86
- def url_list_path
87
- File.join(data_dir, 'urls.txt')
88
- end
89
-
90
- def hostnames
91
- names = []
92
- lines = File.read(url_list_path).split(/[\r\n]+/)
93
- lines.each do |host|
94
- next unless host && !host.empty?
95
- names << "translate.#{host}"
96
- end
97
- names
98
- end
99
-
100
- def unique_servers(list)
101
- server_by_ip = {}
102
- list.each do |server|
103
- next unless server.available
104
- server_by_ip[server.ip] = server
105
- end
106
- server_by_ip.values
107
- end
108
-
109
- def initial_data
110
- hostnames.collect do |host|
111
- server = Server.new
112
- server.host = host
113
- server
114
- end
115
- end
116
-
117
- def read_server_data
118
- return initial_data unless File.exist?(server_data_path)
119
- data = JSON.parse(File.read(server_data_path))
120
- server_list = []
121
- data.each do |entry|
122
- attributes = SERVER_ATTRIBUTES.collect { |i| entry[i.to_s] }
123
- server = Server.new(*attributes)
124
- next unless server.host && !server.host.empty?
125
- server.counter = 0
126
- server_list << server
127
- end
128
- server_list
129
- end
130
-
131
- def save_server_data(servers)
132
- File.write(server_data_path, servers.to_json)
133
- end
134
-
135
- def resolver
136
- resolver = Resolv::DNS.new
137
- resolver.timeouts = 5
138
- resolver
139
- end
140
-
141
- def resolve_ip(host)
142
- resolver.getaddress(host).to_s
143
- end
144
- end
145
- end
146
- end
1
+ require 'concurrent'
2
+ require 'resolv'
3
+ require 'json'
4
+
5
+ module GoogleWebTranslate
6
+
7
+ class ServerList
8
+ class << self
9
+ def servers
10
+ update_servers if @servers.nil?
11
+ @servers.dup
12
+ end
13
+
14
+ def next_server(rate_limit = nil)
15
+ @mutex ||= Mutex.new
16
+ @mutex.synchronize do
17
+ @counter ||= 0
18
+ @counter += 1
19
+
20
+ list = servers.sort_by { |i| i.counter || 0 }
21
+ server = list[0]
22
+ server.counter = @counter
23
+ sleep(rate_limit_delay(server, rate_limit))
24
+ server.last_used_at = Time.now
25
+ server
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ MAX_TTL = 86_400
32
+
33
+ def rate_limit_delay(server, rate_limit)
34
+ return 0 unless rate_limit && server.last_used_at
35
+ delay = rate_limit - (Time.now - server.last_used_at)
36
+ delay < 0 || ENV['TEST'] ? 0 : delay
37
+ end
38
+
39
+ def update_servers
40
+ server_list = read_server_data
41
+ pool = Concurrent::CachedThreadPool.new
42
+ # puts "updating #{server_list.length} servers"
43
+ server_list.each do |server|
44
+ pool.post { update_server(server) }
45
+ end
46
+
47
+ pool.shutdown
48
+ pool.wait_for_termination
49
+ @servers = unique_servers(server_list)
50
+ # puts "#{@servers.length} unique servers found"
51
+ save_server_data(server_list)
52
+ end
53
+
54
+ def update_server(server)
55
+ now = Time.now.to_i
56
+ if server.resolved_at.nil? ||
57
+ now - server.resolved_at > MAX_TTL #|| !server.available
58
+ server.resolved_at = now
59
+ server.ip = resolve_ip(server.host)
60
+ end
61
+ server.available = true
62
+ rescue Resolv::ResolvError
63
+ # puts "server #{server.host} is unavailable: #{e}"
64
+ server.available = false
65
+ end
66
+
67
+ def data_dir
68
+ File.join(__dir__, '..', '..', 'data')
69
+ end
70
+
71
+ def server_data_path
72
+ File.join(data_dir, 'server_data.txt')
73
+ end
74
+
75
+ def url_list_path
76
+ File.join(data_dir, 'urls.txt')
77
+ end
78
+
79
+ def hostnames
80
+ names = []
81
+ lines = File.read(url_list_path).split(/[\r\n]+/)
82
+ lines.each do |host|
83
+ next unless host && !host.empty?
84
+ names << "translate.#{host}"
85
+ end
86
+ names
87
+ end
88
+
89
+ def unique_servers(list)
90
+ server_by_ip = {}
91
+ list.each do |server|
92
+ next unless server.available
93
+ server_by_ip[server.ip] = server
94
+ end
95
+ server_by_ip.values
96
+ end
97
+
98
+ def initial_data
99
+ hostnames.collect do |host|
100
+ server = Server.new
101
+ server.host = host
102
+ server
103
+ end
104
+ end
105
+
106
+ def read_server_data
107
+ return initial_data unless File.exist?(server_data_path)
108
+ data = JSON.parse(File.read(server_data_path))
109
+ server_list = []
110
+ data.each do |entry|
111
+ attributes = SERVER_ATTRIBUTES.collect { |i| entry[i.to_s] }
112
+ server = Server.new(*attributes)
113
+ next unless server.host && !server.host.empty?
114
+ server.counter = 0
115
+ server_list << server
116
+ end
117
+ server_list
118
+ end
119
+
120
+ def save_server_data(servers)
121
+ File.write(server_data_path, servers.to_json)
122
+ end
123
+
124
+ def resolver
125
+ resolver = Resolv::DNS.new
126
+ resolver.timeouts = 5
127
+ resolver
128
+ end
129
+
130
+ def resolve_ip(host)
131
+ resolver.getaddress(host).to_s
132
+ end
133
+ end
134
+ end
135
+ end
@@ -1,3 +1,3 @@
1
- module GoogleWebTranslate
2
- VERSION = '0.2.3'.freeze
3
- end
1
+ module GoogleWebTranslate
2
+ VERSION = '0.2.4'.freeze
3
+ end
@@ -11,7 +11,3 @@ var document = {};
11
11
  function setWindowProperty(key, value) {
12
12
  window[key] = value;
13
13
  }
14
- function generateToken(string, tkk) {
15
- setWindowProperty("TKK", tkk);
16
- return wq(string);
17
- }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: google_web_translate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-01 00:00:00.000000000 Z
11
+ date: 2018-02-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -149,6 +149,7 @@ files:
149
149
  - lib/google_web_translate/cli.rb
150
150
  - lib/google_web_translate/http_client.rb
151
151
  - lib/google_web_translate/result.rb
152
+ - lib/google_web_translate/server.rb
152
153
  - lib/google_web_translate/server_list.rb
153
154
  - lib/google_web_translate/string_escaping.rb
154
155
  - lib/google_web_translate/version.rb
@@ -173,7 +174,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
173
174
  version: '0'
174
175
  requirements: []
175
176
  rubyforge_project:
176
- rubygems_version: 2.6.11
177
+ rubygems_version: 2.7.4
177
178
  signing_key:
178
179
  specification_version: 4
179
180
  summary: Text translation using the google web interface