ud 0.1.3 → 0.2.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 +4 -4
- data/bin/ud +1 -1
- data/lib/ud.rb +46 -91
- data/lib/ud/formatting.rb +5 -3
- data/tests/query_tests.rb +39 -53
- metadata +2 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6c17aeb74c72f8713fd49862c33fa292f256174d
|
4
|
+
data.tar.gz: f1964b4cf50361f5b2765aee3e136cc96d806c61
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cf6a6865b51c9ae2aebd9a063d365b3457aad7aa7a946c706eceb46b299ffcf4a36e981c1d85ee0352693d4c92de840314be300dda31cc9b87742aca105929f4
|
7
|
+
data.tar.gz: e69cc02df921261f58893efb090f8debae155845d4a144f658ad79f1ce15090a9c4903d037bb728cf5a5b9fcd0f16e447b566ecf35566301c71cf364dd79ea92
|
data/bin/ud
CHANGED
@@ -14,7 +14,7 @@ Usage:
|
|
14
14
|
where [options] are:
|
15
15
|
EOS
|
16
16
|
|
17
|
-
opt :ratio, 'Filter by upvotes/downvotes ratio', :type => :float, :default => 0.0
|
17
|
+
opt :ratio, 'Filter by upvotes/downvotes ratio', :type => :float, :default => 0.0, :short => '-r'
|
18
18
|
opt :count, 'Limit the number of definitions', :type => :int, :default => 1, :short => '-n'
|
19
19
|
opt :color, 'Use colorized output', :default => true
|
20
20
|
opt :up, 'Shortcut for \'-r 2\''
|
data/lib/ud.rb
CHANGED
@@ -4,112 +4,67 @@
|
|
4
4
|
require 'uri'
|
5
5
|
require 'json'
|
6
6
|
require 'open-uri'
|
7
|
-
require 'nokogiri'
|
8
7
|
|
9
8
|
require File.dirname(__FILE__) + '/ud/formatting'
|
10
9
|
|
11
10
|
# This module provide some methods to scrape definitions from the Urban
|
12
11
|
# Dictionary website.
|
13
12
|
module UD
|
13
|
+
class << self
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
'0.1.3'
|
18
|
-
end
|
19
|
-
|
20
|
-
# Get the search URL to query for a given term.
|
21
|
-
# [term] the term to search for. It must be a string, spaces are allowed
|
22
|
-
def UD.search_url(term='')
|
23
|
-
param = URI.encode_www_form('term' => term)
|
24
|
-
"http://www.urbandictionary.com/define.php?#{param}"
|
25
|
-
end
|
26
|
-
|
27
|
-
# Get the thumbs (up/down) for a list of definitions' ids.
|
28
|
-
# This is an helper for internal usage.
|
29
|
-
def UD.thumbs(ids)
|
30
|
-
|
31
|
-
param = URI.encode_www_form('ids' => ids.join(','))
|
32
|
-
json = open "http://api.urbandictionary.com/v0/uncacheable?#{param}"
|
33
|
-
|
34
|
-
response = JSON.parse(json.read)
|
35
|
-
thumbs = {}
|
36
|
-
|
37
|
-
response['thumbs'].each do |t|
|
38
|
-
|
39
|
-
thumbs[t['defid']] = {
|
40
|
-
:up => t['thumbs_up'],
|
41
|
-
:down => t['thumbs_down']
|
42
|
-
}
|
43
|
-
|
15
|
+
def version
|
16
|
+
'0.2.0'
|
44
17
|
end
|
45
18
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
el.text.strip.gsub(/\r/, "\n")
|
52
|
-
rescue
|
53
|
-
''
|
54
|
-
end
|
55
|
-
|
56
|
-
# Query the website and return a list of definitions for the provided term.
|
57
|
-
# This list may be empty if there's no result. It only scraps the first
|
58
|
-
# page of results.
|
59
|
-
# [term] the term to search for
|
60
|
-
# [opts] options. This is used by the command-line tool. +:count+ is the
|
61
|
-
# maximum number of results to return, +:ratio+ is the minimum
|
62
|
-
# upvotes/downvotes ratio. Other options may be added in the future.
|
63
|
-
def UD.query(term, *opts)
|
64
|
-
|
65
|
-
opts = {:count => 1, :ratio => 0.0}.merge(opts[0] || {})
|
66
|
-
|
67
|
-
return [] if opts[:count] <= 0
|
68
|
-
|
69
|
-
url = search_url(term)
|
70
|
-
doc = Nokogiri::HTML(open(url))
|
71
|
-
|
72
|
-
return [] unless doc.css('#not_defined_yet').empty?
|
73
|
-
|
74
|
-
words = doc.css('#entries .box')
|
75
|
-
ids = words.take(opts[:count]).map do |w|
|
76
|
-
w.css('.thumb.up').first.attr('data-defid')
|
19
|
+
# Get the search URL to query for a given term.
|
20
|
+
# [term] the term to search for. It must be a string, spaces are allowed
|
21
|
+
def search_url(term='')
|
22
|
+
param = URI.encode_www_form('term' => term)
|
23
|
+
"http://api.urbandictionary.com/v0/define?#{param}"
|
77
24
|
end
|
78
25
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
(t[:up] / t[:down].to_f) < opts[:ratio]
|
85
|
-
end
|
26
|
+
# Get the text of an element. This is an helper for internal usage.
|
27
|
+
def text(el)
|
28
|
+
el.text.strip.gsub(/\r/, "\n")
|
29
|
+
rescue
|
30
|
+
''
|
86
31
|
end
|
87
32
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
33
|
+
# Query the website and return a list of definitions for the provided term.
|
34
|
+
# This list may be empty if there's no result.
|
35
|
+
# [term] the term to search for
|
36
|
+
# [opts] options. This is used by the command-line tool. +:count+ is the
|
37
|
+
# maximum number of results to return, +:ratio+ is the minimum
|
38
|
+
# upvotes/downvotes ratio. Other options may be added in the future.
|
39
|
+
def query(term, *opts)
|
40
|
+
|
41
|
+
opts = {:count => 1, :ratio => 0.0}.merge(opts[0] || {})
|
42
|
+
|
43
|
+
return [] if opts[:count] <= 0
|
44
|
+
|
45
|
+
resp = JSON.parse(open(search_url term).read, :symbolize_names => true)
|
46
|
+
|
47
|
+
resp[:list].map do |res|
|
48
|
+
{
|
49
|
+
:id => res[:defid],
|
50
|
+
:word => res[:word],
|
51
|
+
:author => res[:author],
|
52
|
+
:permalink => res[:permalink],
|
53
|
+
:definition => res[:definition].strip,
|
54
|
+
:example => res[:example].strip,
|
55
|
+
:upvotes => res[:thumbs_up],
|
56
|
+
:downvotes => res[:thumbs_down]
|
57
|
+
}
|
58
|
+
end.keep_if do |d|
|
59
|
+
d[:upvotes]/[d[:downvotes], 0.1].max.to_f >= opts[:ratio]
|
60
|
+
end.take opts[:count]
|
105
61
|
end
|
106
62
|
|
107
|
-
|
63
|
+
# Format results for output
|
64
|
+
# [results] this must be an array of results, as returned by +UD.query+.
|
65
|
+
def format_results(results, color=true)
|
66
|
+
UD::Formatting.text(results, color)
|
67
|
+
end
|
108
68
|
|
109
|
-
# Format results for output
|
110
|
-
# [results] this must be an array of results, as returned by +UD.query+.
|
111
|
-
def UD.format_results(results, color=true)
|
112
|
-
UD::Formatting.text(results, color)
|
113
69
|
end
|
114
|
-
|
115
70
|
end
|
data/lib/ud/formatting.rb
CHANGED
@@ -3,10 +3,11 @@
|
|
3
3
|
|
4
4
|
module UD
|
5
5
|
module Formatting
|
6
|
+
class << self
|
6
7
|
|
7
8
|
# Fit a text in a given width (number of chars). It returns
|
8
9
|
# a list of lines of text.
|
9
|
-
def
|
10
|
+
def fit(txt, width=79)
|
10
11
|
return [] if width < 1
|
11
12
|
|
12
13
|
# from http://stackoverflow.com/a/7567210/735926
|
@@ -18,7 +19,7 @@ module UD
|
|
18
19
|
# the beginning of each element.
|
19
20
|
# [txt] The text to tab, may be a string or a list of strings
|
20
21
|
# [width] The width (number of spaces) of a tab
|
21
|
-
def
|
22
|
+
def tab(txt, width=4)
|
22
23
|
width = 0 if width < 0
|
23
24
|
|
24
25
|
tab = ' ' * width
|
@@ -30,7 +31,7 @@ module UD
|
|
30
31
|
|
31
32
|
# Format results for text output (e.g. in the terminal)
|
32
33
|
# [results] this must be an array of results, as returned by +UD.query+.
|
33
|
-
def
|
34
|
+
def text(results, color=true)
|
34
35
|
require 'colored' if color
|
35
36
|
|
36
37
|
results.map do |r|
|
@@ -61,5 +62,6 @@ module UD
|
|
61
62
|
end.join("\n")
|
62
63
|
end
|
63
64
|
|
65
|
+
end
|
64
66
|
end
|
65
67
|
end
|
data/tests/query_tests.rb
CHANGED
@@ -5,106 +5,92 @@ require File.dirname(__FILE__) + '/fake_responses'
|
|
5
5
|
|
6
6
|
class UD_Formatting_test < Test::Unit::TestCase
|
7
7
|
|
8
|
-
ROOT_URL = 'http://
|
8
|
+
ROOT_URL = 'http://api.urbandictionary.com/v0/define'
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@foo, @bar = [
|
12
|
+
{
|
13
|
+
:id => 1,
|
14
|
+
:author => 'a1',
|
15
|
+
:permalink => 'http://example.com/1',
|
16
|
+
:word => 'foo',
|
17
|
+
:definition => 'A',
|
18
|
+
:example => 'AA',
|
19
|
+
:upvotes => 42,
|
20
|
+
:downvotes => 17
|
21
|
+
|
22
|
+
},
|
23
|
+
{
|
24
|
+
:id => 2,
|
25
|
+
:author => 'a2',
|
26
|
+
:permalink => 'http://example.com/2',
|
27
|
+
:word => 'bar',
|
28
|
+
:definition => 'B',
|
29
|
+
:example => 'BB',
|
30
|
+
:upvotes => 17,
|
31
|
+
:downvotes => 42
|
32
|
+
}
|
33
|
+
]
|
34
|
+
end
|
9
35
|
|
10
36
|
# == UD#search_url == #
|
11
37
|
|
12
38
|
def test_search_url_empty_term
|
13
39
|
assert_equal(
|
14
|
-
"#{ROOT_URL}
|
40
|
+
"#{ROOT_URL}?term=",
|
15
41
|
UD.search_url())
|
16
42
|
assert_equal(
|
17
|
-
"#{ROOT_URL}
|
43
|
+
"#{ROOT_URL}?term=",
|
18
44
|
UD.search_url(''))
|
19
45
|
end
|
20
46
|
|
21
47
|
def test_search_url_spaces_in_term
|
22
48
|
assert_equal(
|
23
|
-
"#{ROOT_URL}
|
49
|
+
"#{ROOT_URL}?term=a+b",
|
24
50
|
UD.search_url('a b'))
|
25
51
|
end
|
26
52
|
|
27
53
|
def test_search_url_encode_special_chars
|
28
54
|
assert_equal(
|
29
|
-
"#{ROOT_URL}
|
55
|
+
"#{ROOT_URL}?term=%3D",
|
30
56
|
UD.search_url('='))
|
31
57
|
end
|
32
58
|
|
33
59
|
def test_search_url
|
34
60
|
assert_equal(
|
35
|
-
"#{ROOT_URL}
|
61
|
+
"#{ROOT_URL}?term=foo",
|
36
62
|
UD.search_url('foo'))
|
37
63
|
end
|
38
64
|
|
39
|
-
# == UD#thumbs == #
|
40
|
-
|
41
|
-
def test_thumbs_no_ids
|
42
|
-
assert_equal({}, UD.thumbs([]))
|
43
|
-
end
|
44
|
-
|
45
|
-
def test_thumbs_one_id
|
46
|
-
assert_equal({42 =>{:up => 2, :down => 1}}, UD.thumbs([42]))
|
47
|
-
end
|
48
|
-
|
49
65
|
# == UD#query == #
|
50
66
|
|
51
67
|
def test_query_no_results
|
52
|
-
assert_equal([], UD.query('
|
68
|
+
assert_equal([], UD.query('fooo'))
|
53
69
|
end
|
54
70
|
|
55
71
|
def test_query_two_results
|
56
72
|
|
57
73
|
expected = [
|
58
|
-
|
59
|
-
:id => '1',
|
60
|
-
:word => 'foo',
|
61
|
-
:definition => 'A',
|
62
|
-
:example => 'AA',
|
63
|
-
:upvotes => 1,
|
64
|
-
:downvotes => 1
|
65
|
-
|
66
|
-
},
|
67
|
-
{
|
68
|
-
:id => '2',
|
69
|
-
:word => 'bar',
|
70
|
-
:definition => 'B',
|
71
|
-
:example => 'BB',
|
72
|
-
:upvotes => 2,
|
73
|
-
:downvotes => 1
|
74
|
-
}
|
74
|
+
@foo, @bar
|
75
75
|
]
|
76
76
|
|
77
|
-
assert_equal(expected, UD.query('
|
77
|
+
assert_equal(expected, UD.query('two_results', :count => 2))
|
78
78
|
end
|
79
79
|
|
80
80
|
def test_query_count
|
81
81
|
expected = [
|
82
|
-
|
83
|
-
:id => '1',
|
84
|
-
:word => 'foo',
|
85
|
-
:definition => 'A',
|
86
|
-
:example => 'AA',
|
87
|
-
:upvotes => 1,
|
88
|
-
:downvotes => 1
|
89
|
-
}
|
82
|
+
@foo
|
90
83
|
]
|
91
84
|
|
92
|
-
assert_equal(expected, UD.query('
|
85
|
+
assert_equal(expected, UD.query('two_results', :count => 1))
|
93
86
|
end
|
94
87
|
|
95
88
|
def test_query_ratio
|
96
89
|
expected = [
|
97
|
-
|
98
|
-
:id => '2',
|
99
|
-
:word => 'bar',
|
100
|
-
:definition => 'B',
|
101
|
-
:example => 'BB',
|
102
|
-
:upvotes => 2,
|
103
|
-
:downvotes => 1
|
104
|
-
}
|
90
|
+
@foo
|
105
91
|
]
|
106
92
|
|
107
|
-
assert_equal(expected, UD.query('
|
93
|
+
assert_equal(expected, UD.query('two_results', :count => 10, :ratio => 1.5))
|
108
94
|
end
|
109
95
|
|
110
96
|
end
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ud
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Baptiste Fontaine
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-01-
|
11
|
+
date: 2014-01-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: nokogiri
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ~>
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 1.5.9
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ~>
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: 1.5.9
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: json
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|