Wordniky 1.0.0.pre.beta.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 +7 -0
- data/lib/wordnik/client.rb +434 -0
- data/lib/wordnik/configuration.rb +43 -0
- data/lib/wordnik/utils.rb +92 -0
- data/lib/wordnik/version.rb +5 -0
- data/lib/wordnik.rb +5 -0
- data/spec/api_spec.rb +200 -0
- data/spec/util_spec.rb +120 -0
- data/spec/vcr/antonyms.yml +57 -0
- data/spec/vcr/audio.yml +64 -0
- data/spec/vcr/definitions.yml +164 -0
- data/spec/vcr/definitions_limit.yml +67 -0
- data/spec/vcr/definitions_noun.yml +265 -0
- data/spec/vcr/definitions_sources.yml +68 -0
- data/spec/vcr/equivalents.yml +57 -0
- data/spec/vcr/examples.yml +96 -0
- data/spec/vcr/frequency.yml +59 -0
- data/spec/vcr/frequency_dirty.yml +59 -0
- data/spec/vcr/hypernyms.yml +58 -0
- data/spec/vcr/hyphenation.yml +57 -0
- data/spec/vcr/hyponyms.yml +58 -0
- data/spec/vcr/phrases.yml +57 -0
- data/spec/vcr/pronunciations.yml +58 -0
- data/spec/vcr/random_word.yml +57 -0
- data/spec/vcr/random_words.yml +57 -0
- data/spec/vcr/related_words.yml +62 -0
- data/spec/vcr/rhymes.yml +57 -0
- data/spec/vcr/scrabble_score.yml +57 -0
- data/spec/vcr/scrabble_score_0.yml +57 -0
- data/spec/vcr/synonyms.yml +57 -0
- data/spec/vcr/top_example.yml +60 -0
- data/spec/vcr/word_of_the_day.yml +76 -0
- data/spec/vcr/wotd.yml +76 -0
- metadata +228 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fb285be6781866ad44de110aa686d8372b3616634cc07f9b585d23193bb7f826
|
4
|
+
data.tar.gz: 60bc52a1e5a023c2e7815acd15b8f6e6aa2e6945b3f364fb73e2fae3dd8b566b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9b7643e1db0df417999b5571783ef63339a50f91ae0cd3aba8fae2e3f90e0b1271d843cfd445d6fc8343b24bcb22a0630be3afc728448ce91039e186e807a950
|
7
|
+
data.tar.gz: 127be08e658425ed5b178c7d949f9b284012a501f753a028c86ad18b83374470bf8cf97478bf66d3de8b884d4cd98dcc910299c00e1cfa261d7460aae07cf29d
|
@@ -0,0 +1,434 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'net/http'
|
5
|
+
|
6
|
+
module Wordnik
|
7
|
+
class Error < StandardError; end
|
8
|
+
|
9
|
+
class Client
|
10
|
+
attr_accessor :configuration, :clean_up
|
11
|
+
|
12
|
+
# Initializes a new Wordnik::Client object.
|
13
|
+
# @param configuration [Wordnik::Configuration] the configuration to use.
|
14
|
+
# @param clean_up [Boolean] whether to clean up the results. Default is true.
|
15
|
+
# If true, the results will be cleaned up in various ways. Generally, this means
|
16
|
+
# 404 (Missing) results will be returned as empty arrays. Other results will generally
|
17
|
+
# be cleaned up to return arrays. Etyomologies will be cleaned up to remove XML tags.
|
18
|
+
def initialize(configuration: nil, http_client: nil, clean_up: true)
|
19
|
+
@configuration = configuration || Configuration.new
|
20
|
+
@http_client = http_client || create_net_https_client
|
21
|
+
@clean_up = clean_up
|
22
|
+
end
|
23
|
+
|
24
|
+
# Fetches audio metadata for a word.
|
25
|
+
# @param word [String] the word to fetch audio metadata for.
|
26
|
+
# @param limit [Integer] the maximum number of results to return. Default is 50.
|
27
|
+
# @return [Array] Array of hashes containing audio metadata.
|
28
|
+
# @raise [Wordnik::Error] if some error is returned by the API.
|
29
|
+
def audio(word, limit = 50)
|
30
|
+
params = { limit: limit }
|
31
|
+
results = call_with_path("word.json/#{word}/audio", params)
|
32
|
+
raise Wordnik::Error, results[:message] if is_error?(results)
|
33
|
+
|
34
|
+
@clean_up && results.is_a?(Hash) ? [] : results
|
35
|
+
end
|
36
|
+
|
37
|
+
# Fetches definitions for a word.
|
38
|
+
# @param word [String] the word to fetch definitions for.
|
39
|
+
# @param limit [Integer] the maximum number of results to return. Default is 200.
|
40
|
+
# @param part_of_speech [String, Array<String>] the parts of speech to filter by. This can be
|
41
|
+
# a single string or an array of strings. Default is nil.
|
42
|
+
# If a single string is provided, it should be comma-separated values
|
43
|
+
# (e.g. "noun,verb") or just "noun"
|
44
|
+
# @param source_dictionaries [String, Array<String>] the source dictionaries to filter by.
|
45
|
+
# This can be a single string or an array of strings. Default is nil.
|
46
|
+
# If a single string is provided, it should be comma-separated values
|
47
|
+
# (e.g. "wiktionary,wordnet") or just "wordnet"
|
48
|
+
# @return [Array] Array of hashes containing definitions.
|
49
|
+
# @raise [Wordnik::Error] if some error is returned by the API.
|
50
|
+
def definitions(word, limit: 200, part_of_speech: nil, source_dictionaries: nil)
|
51
|
+
params = { limit: limit }
|
52
|
+
params[:part_of_speech] = ensure_csv(part_of_speech) if part_of_speech
|
53
|
+
params[:source_dictionaries] = ensure_csv(source_dictionaries) if source_dictionaries
|
54
|
+
results = call_with_path("word.json/#{word}/definitions", params)
|
55
|
+
raise Wordnik::Error, results[:message] if is_error?(results)
|
56
|
+
|
57
|
+
@clean_up ? results.select { |r| r[:text] } : results
|
58
|
+
end
|
59
|
+
|
60
|
+
alias defs definitions
|
61
|
+
|
62
|
+
# Fetches etymologies for a word.
|
63
|
+
# @param word [String] the word to fetch etymologies for.
|
64
|
+
# @return [Array] Array of strings containing etymologies.
|
65
|
+
# @raise [Wordnik::Error] if some error is returned by the API.
|
66
|
+
def etymologies(word)
|
67
|
+
params = {}
|
68
|
+
results = call_with_path("word.json/#{word}/etymologies", params)
|
69
|
+
# foolishly, the API returns a 500 error if the word is not found
|
70
|
+
raise Wordnik::Error, results[:message] if results.is_a?(Hash) && results[:status_code] != 500
|
71
|
+
|
72
|
+
if @clean_up && results.is_a?(Hash)
|
73
|
+
[]
|
74
|
+
elsif results.is_a?(Array)
|
75
|
+
results.map { |r| cleanup_etymology_result(r) }
|
76
|
+
else
|
77
|
+
results
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Fetches examples for a word.
|
82
|
+
# @param word [String] the word to fetch examples for.
|
83
|
+
# @param include_duplicates [Boolean] whether to include duplicate examples
|
84
|
+
# @param skip [Integer] the number of examples to skip. Default is 0.
|
85
|
+
# @param limit [Integer] the maximum number of results to return. Default is 10.
|
86
|
+
# @return [Array, Hash] Array of hashes containing examples, or a hash with an examples: key.
|
87
|
+
# @raise [Wordnik::Error] if some error is returned by the API.
|
88
|
+
def examples(word, include_duplicates: false, skip: 0, limit: 10)
|
89
|
+
params = { limit: limit }
|
90
|
+
params[:include_duplicates] = include_duplicates if include_duplicates
|
91
|
+
params[:skip] = skip if skip&.positive?
|
92
|
+
results = call_with_path("word.json/#{word}/examples", params)
|
93
|
+
raise Wordnik::Error, results[:message] if is_error?(results)
|
94
|
+
|
95
|
+
if @clean_up && is_404?(results)
|
96
|
+
[]
|
97
|
+
elsif @clean_up && results.is_a?(Hash)
|
98
|
+
results[:examples]
|
99
|
+
else
|
100
|
+
results
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Fetches frequency data for a word.
|
105
|
+
# @param word [String] the word to fetch frequency data for.
|
106
|
+
# @param start_year [Integer] the start year for the frequency data. Defaults to 1800.
|
107
|
+
# @param end_year [Integer] the end year for the frequency data. Defaults to 2012.
|
108
|
+
# @return [Array, Hash] Array of hashes containing frequency data, or a hash with a frequency: key.
|
109
|
+
# @raise [Wordnik::Error] if some error is returned by the API.
|
110
|
+
def frequency(word, start_year: nil, end_year: nil)
|
111
|
+
params = {}
|
112
|
+
params[:start_year] = start_year if start_year
|
113
|
+
params[:end_year] = end_year if end_year
|
114
|
+
results = call_with_path("word.json/#{word}/frequency", params)
|
115
|
+
raise Wordnik::Error, results[:message] if is_error?(results)
|
116
|
+
|
117
|
+
if @clean_up && is_404?(results)
|
118
|
+
[]
|
119
|
+
elsif @clean_up && !is_404?(results)
|
120
|
+
frequencies = results[:frequency]
|
121
|
+
# convert the years to integers
|
122
|
+
# and convert the counts to integers
|
123
|
+
frequencies.each do |f|
|
124
|
+
f[:year] = f[:year].to_i
|
125
|
+
f[:count] = f[:count].to_i
|
126
|
+
end
|
127
|
+
frequencies
|
128
|
+
else
|
129
|
+
results
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Fetches hyphenation data for a word.
|
134
|
+
# @param word [String] the word to fetch hyphenation data for.
|
135
|
+
# @param source_dictionary [String] the source dictionary to use. Default is nil.
|
136
|
+
# @param limit [Integer] the maximum number of results to return. Default is 50.
|
137
|
+
# @return [Array] Array of hashes containing hyphenation data.
|
138
|
+
# @raise [Wordnik::Error] if some error is returned by the API.
|
139
|
+
def hyphenation(word, source_dictionary: nil, limit: 50)
|
140
|
+
params = { limit: limit }
|
141
|
+
params[:source_dictionary] = source_dictionary if source_dictionary
|
142
|
+
results = call_with_path("word.json/#{word}/hyphenation", params)
|
143
|
+
raise Wordnik::Error, results[:message] if is_error?(results)
|
144
|
+
|
145
|
+
@clean_up && is_404?(results) ? [] : results
|
146
|
+
end
|
147
|
+
|
148
|
+
# Fetches phrases for a word.
|
149
|
+
# @param word [String] the word to fetch phrases for.
|
150
|
+
# @param limit [Integer] the maximum number of results to return. Default is 5.
|
151
|
+
# @param wlmi [Integer] the minimum weighted mutual information for the phrases returned. What is wlmi?
|
152
|
+
# I don't know.
|
153
|
+
# @return [Array] Array of hashes containing phrases.
|
154
|
+
# @raise [Wordnik::Error] if some error is returned
|
155
|
+
def phrases(word, limit: 5, wlmi: nil)
|
156
|
+
params = { limit: limit }
|
157
|
+
params[:wlmi] = wlmi if wlmi
|
158
|
+
results = call_with_path("word.json/#{word}/phrases", params)
|
159
|
+
raise Wordnik::Error, results[:message] if is_error?(results)
|
160
|
+
|
161
|
+
@clean_up && is_404?(results) ? [] : results
|
162
|
+
end
|
163
|
+
|
164
|
+
# Fetches pronunciations for a word.
|
165
|
+
# @param word [String] the word to fetch pronunciations for.
|
166
|
+
# @param source_dictionary [String] the source dictionary to use. Default is nil (meaning all)
|
167
|
+
# @param type_format [String] the type format to use. Default is nil (meaning all)
|
168
|
+
# @param limit [Integer] the maximum number of results to return. Default is 50.
|
169
|
+
# @return [Array] Array of hashes containing pronunciations.
|
170
|
+
# @raise [Wordnik::Error] if some error is returned by the API.
|
171
|
+
def pronunciations(word, source_dictionary: nil, type_format: nil, limit: 50)
|
172
|
+
params = { limit: limit }
|
173
|
+
params[:source_dictionary] = source_dictionary if source_dictionary
|
174
|
+
params[:type_format] = type_format if type_format
|
175
|
+
results = call_with_path("word.json/#{word}/pronunciations", params)
|
176
|
+
raise Wordnik::Error, results[:message] if is_error?(results)
|
177
|
+
|
178
|
+
if @clean_up
|
179
|
+
if is_404?(results)
|
180
|
+
[]
|
181
|
+
else
|
182
|
+
type_format ? results.select { |r| r[:raw_type] == type_format } : results
|
183
|
+
end
|
184
|
+
else
|
185
|
+
results
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
# Fetches related words for a word.
|
190
|
+
# @param word [String] the word to fetch related words for.
|
191
|
+
# @param relationship_types [String, Array<String>] the relationship types to fetch.
|
192
|
+
# This can be a single string or an array of strings. Default is nil.
|
193
|
+
# If a single string is provided, it should be comma-separated values
|
194
|
+
# (e.g. "form,equivalent") or just "form"
|
195
|
+
# @param limit_per_relationship_type [Integer] the maximum number of results to return per relationship type.
|
196
|
+
def related_words(word, relationship_types: nil, limit_per_relationship_type: 10)
|
197
|
+
params = { limit_per_relationship_type: limit_per_relationship_type }
|
198
|
+
params[:relationship_types] = ensure_csv(relationship_types) if relationship_types
|
199
|
+
results = call_with_path("word.json/#{word}/relatedWords", params)
|
200
|
+
raise Wordnik::Error, results[:message] if is_error?(results)
|
201
|
+
|
202
|
+
@clean_up && is_404?(results) ? [] : results
|
203
|
+
end
|
204
|
+
|
205
|
+
# Fetches the Scrabble score for a word.
|
206
|
+
# @param word [String] the word to fetch the Scrabble score for.
|
207
|
+
# @return [Integer] the Scrabble score for the word.
|
208
|
+
# @raise [Wordnik::Error] if some error is returned by the API.
|
209
|
+
def scrabble_score(word, params = {})
|
210
|
+
results = call_with_path("word.json/#{word}/scrabbleScore", params)
|
211
|
+
raise Wordnik::Error, results[:message] if is_error?(results)
|
212
|
+
|
213
|
+
if @clean_up && is_404?(results)
|
214
|
+
0
|
215
|
+
elsif @clean_up && results.is_a?(Hash)
|
216
|
+
results[:value]
|
217
|
+
else
|
218
|
+
results
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# Fetches the top example for a word.
|
223
|
+
# @param word [String] the word to fetch the top example for.
|
224
|
+
# @return [Hash] the top example for the word.
|
225
|
+
# @raise [Wordnik::Error] if some error is returned by the API.
|
226
|
+
def top_example(word)
|
227
|
+
params = {}
|
228
|
+
results = call_with_path("word.json/#{word}/topExample", params)
|
229
|
+
raise Wordnik::Error, results[:message] if is_error?(results)
|
230
|
+
|
231
|
+
if @clean_up && is_404?(results)
|
232
|
+
{}
|
233
|
+
elsif @clean_up && results.is_a?(Hash)
|
234
|
+
results
|
235
|
+
else
|
236
|
+
results
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
# Fetches a random word.
|
241
|
+
# @param has_dictionary_def [Boolean] only return words with dictionary definitions, defaults to true.
|
242
|
+
# @param include_part_of_speech [String, Array<String>] the parts of speech to include. Default is nil, meaning all.
|
243
|
+
# This can be a single string or an array of strings.
|
244
|
+
# If a single string is provided, it should be comma-separated values,
|
245
|
+
# (e.g. "noun,verb") or just "noun"
|
246
|
+
# @param exclude_part_of_speech [String, Array<String>] the parts of speech to exclude. Default is ni, meaning none.
|
247
|
+
# This can be a single string or an array of strings.
|
248
|
+
# If a single string is provided, it should be comma-separated values,
|
249
|
+
# (e.g. "noun,verb") or just "noun"
|
250
|
+
# @param min_corpus_count [Integer] the minimum corpus count for the word, defaults to nil, meaning no minimum.
|
251
|
+
# @param max_corpus_count [Integer] the maximum corpus count for the word, defaults to nil, meaning no maximum.
|
252
|
+
# @param min_dictionary_count [Integer] the minimum dictionary count for the word, defaults to nil, meaning none.
|
253
|
+
# @param max_dictionary_count [Integer] the maximum dictionary count for the word, defaults to nil, meaning none.
|
254
|
+
# @param min_length [Integer] the minimum length of the word, defaults to nil, meaning no minimum.
|
255
|
+
# @param max_length [Integer] the maximum length of the word, defaults to nil, meaning no maximum.
|
256
|
+
# @return [String, Hash] the random word.
|
257
|
+
# @raise [Wordnik::Error] if some error is returned by the API.
|
258
|
+
def random_word(has_dictionary_def: true, include_part_of_speech: nil, exclude_part_of_speech: nil,
|
259
|
+
min_corpus_count: nil, max_corpus_count: nil, min_dictionary_count: nil, max_dictionary_count: nil,
|
260
|
+
min_length: nil, max_length: nil)
|
261
|
+
params = {}
|
262
|
+
params[:has_dictionary_def] = has_dictionary_def if has_dictionary_def
|
263
|
+
params[:include_part_of_speech] = ensure_csv(include_part_of_speech) if include_part_of_speech
|
264
|
+
params[:exclude_part_of_speech] = ensure_csv(exclude_part_of_speech) if exclude_part_of_speech
|
265
|
+
params[:min_corpus_count] = min_corpus_count if min_corpus_count
|
266
|
+
params[:max_corpus_count] = max_corpus_count if max_corpus_count
|
267
|
+
params[:min_dictionary_count] = min_dictionary_count if min_dictionary_count
|
268
|
+
params[:max_dictionary_count] = max_dictionary_count if max_dictionary_count
|
269
|
+
params[:min_length] = min_length if min_length
|
270
|
+
params[:max_length] = max_length if max_length
|
271
|
+
results = call_with_path('words.json/randomWord', params)
|
272
|
+
raise Wordnik::Error, results[:message] if is_error?(results)
|
273
|
+
|
274
|
+
@clean_up ? results[:word] : results
|
275
|
+
end
|
276
|
+
|
277
|
+
def random_words(has_dictionary_def: true, include_part_of_speech: nil, exclude_part_of_speech: nil,
|
278
|
+
min_corpus_count: nil, max_corpus_count: nil, min_dictionary_count: nil, max_dictionary_count: nil,
|
279
|
+
min_length: nil, max_length: nil, limit: 10)
|
280
|
+
params = { limit: limit }
|
281
|
+
params[:has_dictionary_def] = has_dictionary_def if has_dictionary_def
|
282
|
+
params[:include_part_of_speech] = ensure_csv(include_part_of_speech) if include_part_of_speech
|
283
|
+
params[:exclude_part_of_speech] = ensure_csv(exclude_part_of_speech) if exclude_part_of_speech
|
284
|
+
params[:min_corpus_count] = min_corpus_count if min_corpus_count
|
285
|
+
params[:max_corpus_count] = max_corpus_count if max_corpus_count
|
286
|
+
params[:min_dictionary_count] = min_dictionary_count if min_dictionary_count
|
287
|
+
params[:max_dictionary_count] = max_dictionary_count if max_dictionary_count
|
288
|
+
params[:min_length] = min_length if min_length
|
289
|
+
params[:max_length] = max_length if max_length
|
290
|
+
results = call_with_path('words.json/randomWords', params)
|
291
|
+
raise Wordnik::Error, results[:message] if is_error?(results)
|
292
|
+
|
293
|
+
@clean_up ? results.map { |w| w[:word] } : results
|
294
|
+
end
|
295
|
+
|
296
|
+
# reverse_dictionary is deprecated
|
297
|
+
# def reverse_dictionary(word, params = {})
|
298
|
+
# call_with_path("words.json/reverseDictionary", params)
|
299
|
+
# end
|
300
|
+
|
301
|
+
# search is deprecated
|
302
|
+
# def search(query, params = {})
|
303
|
+
# call_with_path("words.json/search/#{query}", params)
|
304
|
+
# end
|
305
|
+
|
306
|
+
def word_of_the_day(date: nil)
|
307
|
+
params = {}
|
308
|
+
params[:date] = date if date
|
309
|
+
results = call_with_path('words.json/wordOfTheDay', params)
|
310
|
+
raise Wordnik::Error, results[:message] if is_error?(results)
|
311
|
+
|
312
|
+
@clean_up && results == '' ? nil : results
|
313
|
+
end
|
314
|
+
|
315
|
+
alias wotd word_of_the_day
|
316
|
+
|
317
|
+
## Extras!
|
318
|
+
|
319
|
+
# Fetches rhymes for a word.
|
320
|
+
# @param word [String] the word to fetch rhymes for.
|
321
|
+
# @param limit [Integer] the maximum number of results to return. Default is 10.
|
322
|
+
# @return [Array] Array of antonyms.
|
323
|
+
# @raise [Wordnik::Error] if some error is returned by the API.
|
324
|
+
def rhymes(word, limit: 10)
|
325
|
+
related_words(word, relationship_types: :rhyme, limit_per_relationship_type: limit).map do |r|
|
326
|
+
r[:words]
|
327
|
+
end.flatten
|
328
|
+
end
|
329
|
+
|
330
|
+
# Fetches antonyms for a word.
|
331
|
+
# @param word [String] the word to fetch antonyms for.
|
332
|
+
# @param limit [Integer] the maximum number of results to return. Default is 10.
|
333
|
+
# @return [Array] Array of antonyms.
|
334
|
+
# @raise [Wordnik::Error] if some error is returned by the API.
|
335
|
+
def antonyms(word, limit: 10)
|
336
|
+
related_words(word, relationship_types: :antonym, limit_per_relationship_type: limit).map do |r|
|
337
|
+
r[:words]
|
338
|
+
end.flatten
|
339
|
+
end
|
340
|
+
|
341
|
+
# Fetches synonyms for a word.
|
342
|
+
# @param word [String] the word to fetch synonyms for.
|
343
|
+
# @param limit [Integer] the maximum number of results to return. Default is 10.
|
344
|
+
# @return [Array] Array of antonyms.
|
345
|
+
# @raise [Wordnik::Error] if some error is returned by the API.
|
346
|
+
def synonyms(word, limit: 10)
|
347
|
+
related_words(word, relationship_types: :synonym, limit_per_relationship_type: limit).map do |r|
|
348
|
+
r[:words]
|
349
|
+
end.flatten
|
350
|
+
end
|
351
|
+
|
352
|
+
# Fetches hypernyms for a word.
|
353
|
+
# @param word [String] the word to fetch hypernyms for.
|
354
|
+
# @param limit [Integer] the maximum number of results to return. Default is 10.
|
355
|
+
# @return [Array] Array of antonyms.
|
356
|
+
# @raise [Wordnik::Error] if some error is returned by the API.
|
357
|
+
def hypernyms(word, limit: 10)
|
358
|
+
related_words(word, relationship_types: :hypernym, limit_per_relationship_type: limit).map do |r|
|
359
|
+
r[:words]
|
360
|
+
end.flatten
|
361
|
+
end
|
362
|
+
|
363
|
+
# Fetches hyponyms for a word.
|
364
|
+
# @param word [String] the word to fetch hyponyms for.
|
365
|
+
# @param limit [Integer] the maximum number of results to return. Default is 10.
|
366
|
+
# @return [Array] Array of antonyms.
|
367
|
+
# @raise [Wordnik::Error] if some error is returned by the API.
|
368
|
+
def hyponyms(word, limit: 10)
|
369
|
+
related_words(word, relationship_types: :hyponym, limit_per_relationship_type: limit).map do |r|
|
370
|
+
r[:words]
|
371
|
+
end.flatten
|
372
|
+
end
|
373
|
+
|
374
|
+
# Fetches equivalents for a word.
|
375
|
+
# @param word [String] the word to fetch equivalents for.
|
376
|
+
# @param limit [Integer] the maximum number of results to return. Default is 10.
|
377
|
+
# @return [Array] Array of antonyms.
|
378
|
+
# @raise [Wordnik::Error] if some error is returned by the API.
|
379
|
+
def equivalents(word, limit: 10)
|
380
|
+
related_words(word, relationship_types: :equivalent, limit_per_relationship_type: limit).map do |r|
|
381
|
+
r[:words]
|
382
|
+
end.flatten
|
383
|
+
end
|
384
|
+
|
385
|
+
private
|
386
|
+
|
387
|
+
def create_net_https_client
|
388
|
+
client = Net::HTTP.new(@configuration.api_host, @configuration.api_port)
|
389
|
+
client.use_ssl = true
|
390
|
+
client
|
391
|
+
end
|
392
|
+
|
393
|
+
def call(url, params)
|
394
|
+
params[:api_key] = @configuration.api_key
|
395
|
+
uri = URI.parse(url)
|
396
|
+
uri.query = URI.encode_www_form(params)
|
397
|
+
response = @http_client.get(uri)
|
398
|
+
JSON.parse(response.body, symbolize_names: true)
|
399
|
+
end
|
400
|
+
|
401
|
+
def compose_url(path)
|
402
|
+
"https://#{configuration.api_host}/#{configuration.api_version}/#{path}"
|
403
|
+
end
|
404
|
+
|
405
|
+
def normalize_params(params)
|
406
|
+
Wordnik.to_camel_case(params)
|
407
|
+
end
|
408
|
+
|
409
|
+
def call_with_path(path, params)
|
410
|
+
url = compose_url(path)
|
411
|
+
params = normalize_params(params)
|
412
|
+
b = call(url, params)
|
413
|
+
Wordnik.to_snake_case(b)
|
414
|
+
end
|
415
|
+
|
416
|
+
def ensure_csv(value)
|
417
|
+
value.is_a?(Array) ? value.join(',') : value
|
418
|
+
end
|
419
|
+
|
420
|
+
def cleanup_etymology_result(result)
|
421
|
+
# looks like this: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ety>[AS. <ets>hÔøΩsian</ets>.]</ety>\n"
|
422
|
+
# want to return this: "AS. hÔøΩsian"
|
423
|
+
result.gsub(/<.*?>/, '').gsub(/[\n\r]/, '').gsub(/[\[\]]/, '').strip
|
424
|
+
end
|
425
|
+
|
426
|
+
def is_404?(result)
|
427
|
+
result.is_a?(Hash) && result[:status_code] == 404
|
428
|
+
end
|
429
|
+
|
430
|
+
def is_error?(result)
|
431
|
+
result.is_a?(Hash) && result[:status_code] && result[:status_code] != 200 && result[:status_code] != 404
|
432
|
+
end
|
433
|
+
end
|
434
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Wordnik
|
6
|
+
class Configuration
|
7
|
+
attr_accessor :api_key, :api_host, :api_port, :api_version, :connection
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
defaults = {
|
11
|
+
api_host: 'api.wordnik.com',
|
12
|
+
api_port: 443,
|
13
|
+
api_version: 'v4'
|
14
|
+
}
|
15
|
+
loaded = look_for_config_file
|
16
|
+
@api_key = loaded['api_key'] || ENV['WORDNIK_API_KEY']
|
17
|
+
@api_host = loaded['api_host'] || defaults[:api_host]
|
18
|
+
@api_port = loaded['api_port'] || defaults[:api_port]
|
19
|
+
@api_version = loaded['api_version'] || defaults[:api_version]
|
20
|
+
return unless @api_key.nil?
|
21
|
+
|
22
|
+
raise 'No API key found. Please set it in the environment variable WORDNIK_API_KEY or in a .wordnik.yml file'
|
23
|
+
end
|
24
|
+
|
25
|
+
def look_for_config_file
|
26
|
+
if File.exist?('.wordnik.yml')
|
27
|
+
YAML.load_file('.wordnik.yml')
|
28
|
+
elsif File.exist?(File.join(Dir.home, '.wordnik.yml'))
|
29
|
+
YAML.load_file(File.join(Dir.home, '.wordnik.yml'))
|
30
|
+
else
|
31
|
+
{}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
"<Configuration api_key: *****, api_host: #{@api_host}:#{@api_port}, api_version: #{@api_version}>"
|
37
|
+
end
|
38
|
+
|
39
|
+
def inspect
|
40
|
+
to_s
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
module Wordnik
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def to_timestamp_or_string(thing)
|
9
|
+
if thing.is_a?(String)
|
10
|
+
if thing.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(:?\.\d{2,4})?Z$/)
|
11
|
+
return Time.parse(thing)
|
12
|
+
elsif thing.match(/^\d{4}-\d{2}-\d{2}$/)
|
13
|
+
return Date.parse(thing)
|
14
|
+
end
|
15
|
+
|
16
|
+
return thing
|
17
|
+
end
|
18
|
+
thing
|
19
|
+
end
|
20
|
+
|
21
|
+
def capitalize_simple(str)
|
22
|
+
return str if str.empty?
|
23
|
+
|
24
|
+
str[0].upcase + str[1..]
|
25
|
+
end
|
26
|
+
|
27
|
+
def lowercase_simple(str)
|
28
|
+
return str if str.empty?
|
29
|
+
|
30
|
+
str[0].downcase + str[1..]
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_underscore(str)
|
34
|
+
str = str.to_s
|
35
|
+
str.gsub(/::/, '/')
|
36
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
37
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
38
|
+
.tr('-', '_')
|
39
|
+
.downcase
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_camel(str)
|
43
|
+
str = str.to_s
|
44
|
+
return str if str.empty?
|
45
|
+
|
46
|
+
s = str.split('_').map { |part| capitalize_simple(part) }.join
|
47
|
+
lowercase_simple(s)
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_snake_case(thing)
|
51
|
+
if thing.is_a?(Array)
|
52
|
+
return thing.map { |v| to_snake_case(v) }
|
53
|
+
elsif thing.is_a?(String)
|
54
|
+
return to_timestamp_or_string(thing)
|
55
|
+
elsif !thing.is_a?(Hash)
|
56
|
+
return thing
|
57
|
+
end
|
58
|
+
|
59
|
+
# else it's a hash
|
60
|
+
result = {}
|
61
|
+
thing.each do |key, value|
|
62
|
+
if value.is_a?(Hash)
|
63
|
+
value = to_snake_case(value)
|
64
|
+
elsif value.is_a?(Array)
|
65
|
+
value = value.map { |v| to_snake_case(v) }
|
66
|
+
end
|
67
|
+
value = to_timestamp_or_string(value)
|
68
|
+
result[to_underscore(key).to_sym] = value
|
69
|
+
end
|
70
|
+
result
|
71
|
+
end
|
72
|
+
|
73
|
+
def to_camel_case(thing)
|
74
|
+
if thing.is_a?(Array)
|
75
|
+
return thing.map { |v| to_camel_case(v) }
|
76
|
+
elsif !thing.is_a?(Hash)
|
77
|
+
return thing
|
78
|
+
end
|
79
|
+
|
80
|
+
# else it's a hash
|
81
|
+
result = {}
|
82
|
+
thing.each do |key, value|
|
83
|
+
if value.is_a?(Hash)
|
84
|
+
value = to_camel_case(value)
|
85
|
+
elsif value.is_a?(Array)
|
86
|
+
value = value.map { |v| to_camel_case(v) }
|
87
|
+
end
|
88
|
+
result[to_camel(key).to_sym] = value
|
89
|
+
end
|
90
|
+
result
|
91
|
+
end
|
92
|
+
end
|