-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
34 changed files
with
677 additions
and
185 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,3 +22,5 @@ erl_crash.dump | |
# Ignore package tarball (built via "mix hex.build"). | ||
authoritex-*.tar | ||
|
||
/.elixir_ls/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
defmodule Authoritex.GeoNames do | ||
@moduledoc "Authoritex implementation for GeoNames webservice" | ||
@behaviour Authoritex | ||
|
||
@http_uri_base "https://sws.geonames.org/" | ||
|
||
@error_codes %{ | ||
"10" => "Authorization Exception", | ||
"11" => "record does not exist", | ||
"12" => "other error", | ||
"13" => "database timeout", | ||
"14" => "invalid parameter", | ||
"15" => "no result found", | ||
"16" => "duplicate exception", | ||
"17" => "postal code not found", | ||
"18" => "daily limit of credits exceeded", | ||
"19" => "hourly limit of credits exceeded", | ||
"20" => "weekly limit of credits exceeded", | ||
"21" => "invalid input", | ||
"22" => "server overloaded exception", | ||
"23" => "service not implemented", | ||
"24" => "radius too large", | ||
"27" => "maxRows too large" | ||
} | ||
|
||
@impl Authoritex | ||
def can_resolve?(@http_uri_base <> _), do: true | ||
def can_resolve?(_), do: false | ||
|
||
@impl Authoritex | ||
def code, do: "geonames" | ||
|
||
@impl Authoritex | ||
def description, do: "GeoNames geographical database" | ||
|
||
@impl Authoritex | ||
def fetch(id) do | ||
@http_uri_base <> geoname_id = id | ||
|
||
case HTTPoison.get( | ||
"http://api.geonames.org/getJSON", | ||
[{"User-Agent", "Authoritex"}], | ||
params: [ | ||
geonameId: geoname_id, | ||
username: username() | ||
] | ||
) do | ||
{:ok, %{body: response, status_code: 200}} -> | ||
parse_fetch_result(response) | ||
|
||
{:ok, %{body: response, status_code: status_code}} -> | ||
{:error, parse_geonames_error(response, status_code)} | ||
|
||
{:error, error} -> | ||
{:error, error} | ||
end | ||
end | ||
|
||
@impl Authoritex | ||
def search(query, max_results \\ 30) do | ||
case HTTPoison.get( | ||
"http://api.geonames.org/searchJSON", | ||
[{"User-Agent", "Authoritex"}], | ||
params: [ | ||
q: query, | ||
username: username(), | ||
maxRows: max_results | ||
] | ||
) do | ||
{:ok, %{body: response, status_code: 200}} -> | ||
{:ok, parse_search_result(response)} | ||
|
||
{:ok, %{body: response, status_code: status_code}} -> | ||
{:error, parse_geonames_error(response, status_code)} | ||
|
||
{:error, error} -> | ||
{:error, error} | ||
end | ||
end | ||
|
||
defp parse_search_result(response) do | ||
response | ||
|> Jason.decode!() | ||
|> Map.get("geonames") | ||
|> Enum.map(fn result -> | ||
%{ | ||
id: @http_uri_base <> to_string(result["geonameId"]), | ||
label: result["name"], | ||
hint: parse_hint(result) | ||
} | ||
end) | ||
end | ||
|
||
defp parse_fetch_result(%{"status" => %{"message" => message, "value" => error_code}}) do | ||
{:error, "#{error_description(to_string(error_code))} (#{to_string(error_code)}). #{message}"} | ||
end | ||
|
||
defp parse_fetch_result(%{"geonameId" => geoname_id, "name" => name} = response) do | ||
hint = parse_hint(response) | ||
|
||
{:ok, | ||
Enum.into( | ||
[ | ||
id: @http_uri_base <> to_string(geoname_id), | ||
label: name, | ||
hint: hint, | ||
qualified_label: Enum.join(Enum.filter([name, hint], & &1), ", ") | ||
], | ||
%{} | ||
)} | ||
end | ||
|
||
defp parse_fetch_result(response) do | ||
case Jason.decode(response) do | ||
{:ok, response} -> | ||
parse_fetch_result(response) | ||
|
||
{:error, error} -> | ||
{:error, {:bad_response, error}} | ||
end | ||
end | ||
|
||
defp parse_geonames_error(response, status_code) do | ||
case Jason.decode(response) do | ||
{:ok, %{"status" => %{"value" => 11}}} -> | ||
status_code | ||
|
||
{:ok, %{"status" => %{"message" => message, "value" => error_code}}} -> | ||
"Status #{status_code}: #{error_description(to_string(error_code))} (#{ | ||
to_string(error_code) | ||
}). #{message}" | ||
|
||
{:error, error} -> | ||
{:bad_response, error} | ||
end | ||
end | ||
|
||
defp parse_hint(%{"fcode" => "PCLI"}), do: nil | ||
defp parse_hint(%{"fcode" => "RGN", "countryName" => countryName}), do: countryName | ||
defp parse_hint(%{"fcode" => "ADM1", "countryName" => countryName}), do: countryName | ||
|
||
defp parse_hint(%{"fcode" => _, "countryName" => country_name, "adminName1" => admin_name}) do | ||
case Enum.join(Enum.reject([admin_name, country_name], &(&1 == "")), ", ") do | ||
"" -> | ||
nil | ||
|
||
hint -> | ||
hint | ||
end | ||
end | ||
|
||
defp parse_hint(_), do: nil | ||
|
||
defp error_description(code) do | ||
@error_codes | ||
|> Map.get(code) | ||
end | ||
|
||
# coveralls-ignore-start | ||
defp username() do | ||
System.get_env("GEONAMES_USERNAME") || | ||
Application.get_env(:authoritex, :geonames_username) | ||
end | ||
|
||
# coveralls-ignore-stop | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
defmodule Authoritex.GeoNamesTest do | ||
alias Authoritex.GeoNames | ||
|
||
use Authoritex.TestCase, | ||
module: Authoritex.GeoNames, | ||
code: "geonames", | ||
description: "GeoNames geographical database", | ||
test_uris: [ | ||
"https://sws.geonames.org/4302561" | ||
], | ||
bad_uri: "https://sws.geonames.org/43025619", | ||
expected: [ | ||
hint: "Kentucky, United States", | ||
id: "https://sws.geonames.org/4302561", | ||
label: "Nicholasville", | ||
qualified_label: "Nicholasville, Kentucky, United States" | ||
], | ||
search_result_term: "Kentucky", | ||
search_count_term: "Kentucky" | ||
|
||
describe "errors" do | ||
test "fetch" do | ||
use_cassette "geonames_500", match_requests_on: [:query], custom: true do | ||
assert GeoNames.fetch("https://sws.geonames.org/4560349") == | ||
{:error, "Status 500: server overloaded exception (22). Internal Server Error."} | ||
end | ||
end | ||
|
||
test "search" do | ||
use_cassette "geonames_500", match_requests_on: [:query], custom: true do | ||
assert GeoNames.search("Authority Down") == | ||
{:error, "Status 500: server overloaded exception (22). Internal Server Error."} | ||
end | ||
end | ||
|
||
test "GeoNames invlid parameter response" do | ||
use_cassette "geonames_invalid_parameter", match_requests_on: [:query] do | ||
assert GeoNames.fetch("https://sws.geonames.org/wrong") == | ||
{:error, "invalid parameter (14). For input string: \"wrong\""} | ||
end | ||
end | ||
|
||
test "GeoNames custom hint for `fcode` `RGN` is `countryName`" do | ||
use_cassette "geonames_custom_hint", match_requests_on: [:query] do | ||
assert GeoNames.fetch("https://sws.geonames.org/11887750") == | ||
{:ok, | ||
%{ | ||
hint: "United States", | ||
id: "https://sws.geonames.org/11887750", | ||
label: "Midwest", | ||
qualified_label: "Midwest, United States" | ||
}} | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
[ | ||
{ | ||
"request": { | ||
"body": "", | ||
"headers": { | ||
"User-Agent": "Authoritex" | ||
}, | ||
"method": "get", | ||
"options": [], | ||
"request_body": "", | ||
"url": "http://api.geonames.org/getJSON?geonameId=4560349&<<geonames_username>>" | ||
}, | ||
"response": { | ||
"status_code": 500, | ||
"headers": { | ||
"Content-Type": "application/json;charset=UTF-8" | ||
}, | ||
"body": "{\"status\":{\"message\":\"Internal Server Error.\",\"value\":22}}" | ||
} | ||
}, | ||
{ | ||
"request": { | ||
"body": "", | ||
"headers": { | ||
"User-Agent": "Authoritex" | ||
}, | ||
"method": "get", | ||
"options": [], | ||
"request_body": "", | ||
"url": "http://api.geonames.org/searchJSON?q=Authority+Down&<<geonames_username>>&maxRows=30" | ||
}, | ||
"response": { | ||
"status_code": 500, | ||
"headers": { | ||
"Content-Type": "application/json;charset=UTF-8" | ||
}, | ||
"body": "{\"status\":{\"message\":\"Internal Server Error.\",\"value\":22}}" | ||
} | ||
} | ||
] |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 19 additions & 19 deletions
38
test/fixtures/vcr_cassettes/authoritex_search_results.json
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
[ | ||
{ | ||
"request": { | ||
"body": "", | ||
"headers": { | ||
"User-Agent": "Authoritex" | ||
}, | ||
"method": "get", | ||
"options": [], | ||
"request_body": "", | ||
"url": "http://api.geonames.org/getJSON?geonameId=11887750&<<geonames_username>>" | ||
}, | ||
"response": { | ||
"binary": false, | ||
"body": "{\"timezone\":{\"gmtOffset\":-6,\"timeZoneId\":\"America/Chicago\",\"dstOffset\":-5},\"bbox\":{\"east\":-80.518693,\"south\":35.995683,\"north\":49.384358,\"west\":-104.05769800000002,\"accuracyLevel\":0},\"asciiName\":\"Midwest\",\"astergdem\":338,\"countryId\":\"6252001\",\"fcl\":\"L\",\"srtm3\":335,\"countryCode\":\"US\",\"lat\":\"42.65982\",\"fcode\":\"RGN\",\"continentCode\":\"NA\",\"lng\":\"-93.93863\",\"geonameId\":11887750,\"toponymName\":\"Midwest\",\"population\":65000000,\"wikipediaURL\":\"en.wikipedia.org/wiki/Midwestern_United_States\",\"adminName5\":\"\",\"adminName4\":\"\",\"adminName3\":\"\",\"alternateNames\":[{\"name\":\"https://en.wikipedia.org/wiki/Midwestern_United_States\",\"lang\":\"link\"},{\"isPreferredName\":true,\"name\":\"Midwestern United States\"}],\"adminName2\":\"\",\"name\":\"Midwest\",\"fclName\":\"parks,area, ...\",\"countryName\":\"United States\",\"fcodeName\":\"region\",\"adminName1\":\"\"}", | ||
"headers": { | ||
"Date": "Mon, 18 May 2020 14:04:37 GMT", | ||
"Server": "Apache/2.4.6 (CentOS) mod_jk/1.2.41 OpenSSL/1.0.1e-fips PHP/5.4.16", | ||
"Cache-Control": "no-cache", | ||
"Access-Control-Allow-Origin": "*", | ||
"Transfer-Encoding": "chunked", | ||
"Content-Type": "application/json;charset=UTF-8" | ||
}, | ||
"status_code": 200, | ||
"type": "ok" | ||
} | ||
} | ||
] |
Oops, something went wrong.