-
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
32 changed files
with
601 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,157 @@ | ||
defmodule Authoritex.GeoNames do | ||
@moduledoc "Authoritex implementation for GeoNames webservice" | ||
@behaviour Authoritex | ||
|
||
@http_uri_base "https://sws.geonames.org/" | ||
|
||
@username System.get_env("GEONAMES_USERNAME") || | ||
Application.get_env(:authoritex, :geonames_username) | ||
|
||
@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["adminName1"], result["countryName"]) | ||
} | ||
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, | ||
"adminName1" => adminName1, | ||
"countryName" => countryName | ||
}) do | ||
hint = parse_hint(adminName1, countryName) | ||
|
||
{: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(admin_name, country_name) do | ||
parse_hint(Enum.join(Enum.reject([admin_name, country_name], &(&1 == "")), ", ")) | ||
end | ||
|
||
defp parse_hint(""), do: nil | ||
defp parse_hint(hint), do: hint | ||
|
||
defp error_description(code) do | ||
@error_codes | ||
|> Map.get(code) | ||
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,43 @@ | ||
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 | ||
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=43025619&<<geonames_username>>" | ||
}, | ||
"response": { | ||
"binary": false, | ||
"body": "{\"status\":{\"message\":\"the geoname feature does not exist.\",\"value\":11}}", | ||
"headers": { | ||
"Date": "Fri, 15 May 2020 19:28:44 GMT", | ||
"Server": "Apache/2.4.6 (CentOS) mod_jk/1.2.46 OpenSSL/1.0.2k-fips", | ||
"Cache-Control": "no-cache", | ||
"Access-Control-Allow-Origin": "*", | ||
"Content-Length": "71", | ||
"Content-Type": "application/json;charset=UTF-8" | ||
}, | ||
"status_code": 404, | ||
"type": "ok" | ||
} | ||
} | ||
] |
Oops, something went wrong.