slg 0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 138f7e46a189d5f94aec8149144f460938dff2f74e3f86650ac323874be91c3e
4
+ data.tar.gz: 7b5b412986a25443036a2f8dabef508d2b59242884542f443837a9389c512bda
5
+ SHA512:
6
+ metadata.gz: b9c3b92bad04d21f66128e0cfdd1cc6001f8a70eb3323c86b2e42dafa95756d7af2ff5e4a109c9ccc70e6876d6d50bd8ca9fd19ad176098bce6152520e35e071
7
+ data.tar.gz: 8e04ce6ff7b6086edcfc408587a8f451861c2a0055859da63c92f8c53d177946413f52dd2727e2a5ab2ccbdf7525096f4429f32c51544ebf44d0816a5b61fde2
checksums.yaml.gz.sig ADDED
Binary file
data.tar.gz.sig ADDED
Binary file
data/bin/slg ADDED
@@ -0,0 +1,39 @@
1
+ #! /usr/bin/env ruby
2
+ # -*- coding: UTF-8 -*-
3
+
4
+ # clean interrupt
5
+ trap("INT") { abort }
6
+
7
+ require "optimist"
8
+ require "slg"
9
+
10
+ opts = Optimist.options do
11
+ version "slg #{Slg.version}"
12
+ banner <<-EOS
13
+ Slg is a command-line tool to scrape definitions from Slengo.it.
14
+
15
+ Usage:
16
+ slg [options] <word(s)>
17
+ where [options] are:
18
+ EOS
19
+
20
+ opt :count, "Limit the number of definitions", :type => :int, :default => 1, :short => "-n"
21
+ opt :color, "Use colorized output", :default => true
22
+ opt :browser, "Open the results in a browser window", :short => "-b"
23
+ end
24
+
25
+ Optimist.die :count, "must be non-negative" if opts[:count] < 0
26
+
27
+ if ARGV.empty?
28
+ puts "Error: No word provided. Use -h or --help to see the help."
29
+ exit 1
30
+ end
31
+
32
+ term = ARGV.join " "
33
+
34
+ if opts[:browser]
35
+ Slg.open_url(term)
36
+ else
37
+ q = Slg.query(ARGV.join(" "), opts)
38
+ puts Slg.format_results(q, opts[:color])
39
+ end
data/lib/slg.rb ADDED
@@ -0,0 +1,107 @@
1
+ # -*- coding: UTF-8 -*-
2
+
3
+ require "uri"
4
+ require "open-uri"
5
+ require "nokogiri"
6
+
7
+ require "ud/formatting"
8
+
9
+ # Most of this code is copy/pasted from UD.
10
+ # TODO generalize the code in UD and reuse it here.
11
+
12
+ # This module provide some methods to scrape definitions from Slengo.it.
13
+ module Slg
14
+ class << self
15
+ # @return [String] the current gem's version
16
+ def version
17
+ "0.0.1"
18
+ end
19
+
20
+ WWW_ROOT = "https://slengo.it"
21
+
22
+ # Get the search URL to query for a given term.
23
+ # @param term [String] the term to search for. It must be a string, spaces
24
+ # are allowed.
25
+ # @return [String]
26
+ def search_url(term)
27
+ param = URI.encode_www_form_component(term).gsub(/\+/, "%20")
28
+ "#{WWW_ROOT}/define/#{param}"
29
+ end
30
+
31
+ # Open the search URL in the user's browser
32
+ # @param term [String] the term to search for. It must be a string, spaces
33
+ # are allowed.
34
+ # @return [Nil]
35
+ def open_url(term)
36
+ system open_cmd, search_url(term)
37
+ end
38
+
39
+ # Query the website and return a list of definitions for the provided term.
40
+ # This list may be empty if there's no result.
41
+ # @param term [String] the term to search for
42
+ # @param opts [Hash] options. This is used by the command-line tool.
43
+ # +:count+ is the maximum number of results to return
44
+ # @return [Array<Hash>]
45
+ def query(term, opts = {})
46
+ url = search_url(term)
47
+ text = OpenURI.open_uri url
48
+
49
+ opts = { :count => 1 }.merge(opts || {})
50
+
51
+ return [] if opts[:count] <= 0
52
+
53
+ doc = Nokogiri::HTML.parse text
54
+
55
+ doc.css("article.definition-card").map do |elt|
56
+ examples = elt.css(".word-examples li").map(&:text).map(&:strip)
57
+ example = examples.join "\n\n"
58
+
59
+ votes = elt.css(".votes-container .v-progress-linear")
60
+ # Slengo.it uses percentages instead of number of votes
61
+ upvotes = votes.attr("aria-valuenow").to_s.to_i
62
+ downvotes = 100 - upvotes
63
+
64
+ header_p = elt.css("header p").first
65
+
66
+ definition = elt.css("div.word-definition").text
67
+ # Remove 'see also'
68
+ definition.gsub! /\bCfr\..+/m, ""
69
+ definition.strip!
70
+
71
+ {
72
+ # There's no :id nor :author
73
+ # For some reason the selector 'h1.word-title' work in JS in the
74
+ # browser but not with Nokogiri.
75
+ :word => header_p.text.strip,
76
+ :permalink => url,
77
+ :definition => definition,
78
+ :example => example,
79
+ :upvotes => upvotes,
80
+ :downvotes => downvotes,
81
+ # TODO add region as well
82
+ }
83
+
84
+ end.take opts[:count]
85
+ end
86
+
87
+ # Format results for output
88
+ # @param results [Array] this must be an array of results, as returned by
89
+ # +UD.query+.
90
+ # @param color [Boolean] colored output
91
+ # @return [String]
92
+ def format_results(results, color = true)
93
+ UD::Formatting.text(results, color)
94
+ end
95
+
96
+ def open_cmd
97
+ case RbConfig::CONFIG["host_os"]
98
+ when /darwin/
99
+ "open"
100
+ when /bsd|linux/
101
+ "xdg-open"
102
+ when /cygwin|mingw|mswin/
103
+ "start"
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,44 @@
1
+ #! /usr/bin/env ruby
2
+ # -*- coding: UTF-8 -*-
3
+
4
+ require File.dirname(__FILE__) + '/fake_responses'
5
+
6
+ class Slg_Query_test < Test::Unit::TestCase
7
+ def setup
8
+ @foo, @bar = [
9
+ {
10
+ :definition=>"Foo foo.",
11
+ :downvotes=>0,
12
+ :example=> "foo ex 1\n\nfoo ex 2",
13
+ :permalink=>"https://slengo.it/define/culo",
14
+ :upvotes=>100,
15
+ :word=>"foo",
16
+ },
17
+ {
18
+ :definition=>"Bar bar.",
19
+ :downvotes=>10,
20
+ :example=>"bar ex",
21
+ :permalink=>"https://slengo.it/define/culo",
22
+ :upvotes=>90,
23
+ :word=>"foo",
24
+ }
25
+ ]
26
+ end
27
+
28
+ def test_search_url
29
+ assert_equal("https://slengo.it/define/foo", Slg.search_url('foo'))
30
+ end
31
+
32
+ def test_query_no_results
33
+ assert_equal([], Slg.query('foooo'))
34
+ end
35
+
36
+ def test_query_two_results
37
+ assert_equal([@foo, @bar], Slg.query('culo', :count => 2))
38
+ end
39
+
40
+ def test_query_count
41
+ assert_equal([@foo], Slg.query('culo', :count => 1))
42
+ end
43
+ end
44
+
data/tests/tests.rb ADDED
@@ -0,0 +1,53 @@
1
+ #! /usr/bin/env ruby
2
+ # -*- coding: UTF-8 -*-
3
+
4
+ ci = ENV["CI"] || ENV["CONTINUOUS_INTEGRATION"]
5
+
6
+ if ci
7
+ require 'coveralls'
8
+ Coveralls.wear!
9
+ end
10
+
11
+ require 'test/unit'
12
+ require 'simplecov'
13
+
14
+ test_dir = File.expand_path( File.dirname(__FILE__) )
15
+
16
+ SimpleCov.formatter = Coveralls::SimpleCov::Formatter if ci
17
+ SimpleCov.start { add_filter '/tests/' }
18
+
19
+ require 'slg'
20
+
21
+ for t in Dir.glob( File.join( test_dir, '*_tests.rb' ) )
22
+ require t
23
+ end
24
+
25
+ class SlgTests < Test::Unit::TestCase
26
+
27
+ def test_slg_version
28
+ assert(Slg.version =~ /^\d+\.\d+\.\d+/)
29
+ end
30
+
31
+ def test_slg_open_cmd
32
+ os = RbConfig::CONFIG["host_os"]
33
+
34
+ RbConfig::CONFIG["host_os"] = "darwin"
35
+ assert_equal "open", Slg.send(:open_cmd)
36
+
37
+ RbConfig::CONFIG["host_os"] = "linux"
38
+ assert_equal "xdg-open", Slg.send(:open_cmd)
39
+
40
+ RbConfig::CONFIG["host_os"] = "bsd"
41
+ assert_equal "xdg-open", Slg.send(:open_cmd)
42
+
43
+ RbConfig::CONFIG["host_os"] = "cygwin"
44
+ assert_equal "start", Slg.send(:open_cmd)
45
+
46
+ ensure
47
+ RbConfig::CONFIG["host_os"] = os
48
+ end
49
+
50
+ end
51
+
52
+
53
+ exit Test::Unit::AutoRunner.run
metadata ADDED
@@ -0,0 +1,200 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: slg
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Baptiste Fontaine
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIID/DCCAmSgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAkMSIwIAYDVQQDDBliL0RD
14
+ PXB0aXN0ZWZvbnRhaW5lL0RDPWZyMB4XDTIwMDMwNDE5MDMyMVoXDTIxMDMwNDE5
15
+ MDMyMVowJDEiMCAGA1UEAwwZYi9EQz1wdGlzdGVmb250YWluZS9EQz1mcjCCAaIw
16
+ DQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAKdjTwN/gnJ3WHxKeusaRN1o902Q
17
+ BmIRgdtbhpsHtgUruKNujutEBpmhG1fka8+mujhqh885blckeC8hXgqpHGK1MsJU
18
+ tgsNB2F2Nvof/uGBzi+OZ76HPLmfvJFb/KUiwrh08jTbFftMBCmuekbxBajt2N2F
19
+ shF6DFEqO2hl/itVt5UeIZhpIZvO7qSZ9FtLRXs0q2O27h4QfAv6XobNDwH5TBs5
20
+ z+EYufgTtupf26xW0v6z2NDG6z36Eap7QAwoivuPCuXO+IPgxhubtGvFYSo7ygP4
21
+ RbYsaGucRneCCzezTD+i1LnhGt9TCbQjdvidgM+i616JC/HRXglM0apgBZSjayoI
22
+ XHoajIajnU+570cu01Wsa+SF9m4stKao0hLnCUMeYybmA/Ilk58nJ2xZJWMULu76
23
+ 7Ttzead1Ah25ZdWefKG5FIGkpezEp4z/YihGEJt+hxS7Aa2xYiIlnYFwUno530/8
24
+ So5Ibqdd3pMKJDUQJvGIBhsQIXF4Iogk4txoPwIDAQABozkwNzAJBgNVHRMEAjAA
25
+ MAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUsV1eKnEFtVRwyz6/nTuharH3G+UwDQYJ
26
+ KoZIhvcNAQELBQADggGBAJz7tbRe/iyMthV7fdqnhFv0SZo1UVWZSaIjB39W4lUi
27
+ 7X1Smag2Fe7IqARUPLn2e49ObyupAmTi0zHoSG/+HsBUqNPPoVW1Y67dtrMM49o7
28
+ qSN66EogB4nvGdvqJ9eOlioiAX7vczWmQjfSONuk0ihOfaTChD7LwoPptTUu/Q6+
29
+ aT8zz7TH+sxxx+D09Q9+Ywf1RVnUe+i1PTo8kadnHIQdeBPudKrw5GWcIoLz1V16
30
+ A+j/SNEUqY1ui8TBX6axkd8vh6C1YcVAFCcdrxTMFTeB1irvL8jns6SulRHM08UC
31
+ 9NR+YthP16QuQzb5R2wIGX6WT11cnIpo0LzTnY/QSZGgwJkuLalBLzUssMiVnoSX
32
+ rVdmQBLrs38YcJouqHpf0wCGygf5430Bq4nCu0xUaH5umPcwJE9qaF1ZfgSCfZEz
33
+ Qe5fflfwGHtlmT6SWZoQD48xF/ILJ+cLTpF79ardGYnWT6N7VUAI5lKp7OjZYd+q
34
+ wwYlmlBW0Femxy5WoxzECQ==
35
+ -----END CERTIFICATE-----
36
+ date: 2020-03-23 00:00:00.000000000 Z
37
+ dependencies:
38
+ - !ruby/object:Gem::Dependency
39
+ name: optimist
40
+ requirement: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - "~>"
43
+ - !ruby/object:Gem::Version
44
+ version: '3.0'
45
+ type: :runtime
46
+ prerelease: false
47
+ version_requirements: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - "~>"
50
+ - !ruby/object:Gem::Version
51
+ version: '3.0'
52
+ - !ruby/object:Gem::Dependency
53
+ name: colored
54
+ requirement: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - "~>"
57
+ - !ruby/object:Gem::Version
58
+ version: '1.2'
59
+ type: :runtime
60
+ prerelease: false
61
+ version_requirements: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - "~>"
64
+ - !ruby/object:Gem::Version
65
+ version: '1.2'
66
+ - !ruby/object:Gem::Dependency
67
+ name: ud
68
+ requirement: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - "~>"
71
+ - !ruby/object:Gem::Version
72
+ version: '0.3'
73
+ type: :runtime
74
+ prerelease: false
75
+ version_requirements: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: '0.3'
80
+ - !ruby/object:Gem::Dependency
81
+ name: nokogiri
82
+ requirement: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - "~>"
85
+ - !ruby/object:Gem::Version
86
+ version: '1.10'
87
+ type: :runtime
88
+ prerelease: false
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - "~>"
92
+ - !ruby/object:Gem::Version
93
+ version: '1.10'
94
+ - !ruby/object:Gem::Dependency
95
+ name: simplecov
96
+ requirement: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - "~>"
99
+ - !ruby/object:Gem::Version
100
+ version: '0.18'
101
+ type: :development
102
+ prerelease: false
103
+ version_requirements: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - "~>"
106
+ - !ruby/object:Gem::Version
107
+ version: '0.18'
108
+ - !ruby/object:Gem::Dependency
109
+ name: rake
110
+ requirement: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - "~>"
113
+ - !ruby/object:Gem::Version
114
+ version: '12.3'
115
+ type: :development
116
+ prerelease: false
117
+ version_requirements: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - "~>"
120
+ - !ruby/object:Gem::Version
121
+ version: '12.3'
122
+ - !ruby/object:Gem::Dependency
123
+ name: test-unit
124
+ requirement: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - "~>"
127
+ - !ruby/object:Gem::Version
128
+ version: '3.3'
129
+ type: :development
130
+ prerelease: false
131
+ version_requirements: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - "~>"
134
+ - !ruby/object:Gem::Version
135
+ version: '3.3'
136
+ - !ruby/object:Gem::Dependency
137
+ name: webmock
138
+ requirement: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - "~>"
141
+ - !ruby/object:Gem::Version
142
+ version: '3.8'
143
+ type: :development
144
+ prerelease: false
145
+ version_requirements: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - "~>"
148
+ - !ruby/object:Gem::Version
149
+ version: '3.8'
150
+ - !ruby/object:Gem::Dependency
151
+ name: coveralls
152
+ requirement: !ruby/object:Gem::Requirement
153
+ requirements:
154
+ - - "~>"
155
+ - !ruby/object:Gem::Version
156
+ version: '0.8'
157
+ type: :development
158
+ prerelease: false
159
+ version_requirements: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - "~>"
162
+ - !ruby/object:Gem::Version
163
+ version: '0.8'
164
+ description: Get words' definitions from Slengo on the command-line.
165
+ email: b@ptistefontaine.fr
166
+ executables:
167
+ - slg
168
+ extensions: []
169
+ extra_rdoc_files: []
170
+ files:
171
+ - bin/slg
172
+ - lib/slg.rb
173
+ - tests/query_tests.rb
174
+ - tests/tests.rb
175
+ homepage: https://github.com/bfontaine/slg
176
+ licenses:
177
+ - MIT
178
+ metadata: {}
179
+ post_install_message:
180
+ rdoc_options: []
181
+ require_paths:
182
+ - lib
183
+ required_ruby_version: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ required_rubygems_version: !ruby/object:Gem::Requirement
189
+ requirements:
190
+ - - ">="
191
+ - !ruby/object:Gem::Version
192
+ version: '0'
193
+ requirements: []
194
+ rubygems_version: 3.1.2
195
+ signing_key:
196
+ specification_version: 4
197
+ summary: Slengo.it unofficial scrapper
198
+ test_files:
199
+ - tests/tests.rb
200
+ - tests/query_tests.rb
metadata.gz.sig ADDED
Binary file