Current section
Files
Jump to
Current section
Files
src/sunny@api@geocoding.erl
-module(sunny@api@geocoding).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([location_to_position/1, params/1, set_count/2, set_language/2, get_request/2, get_result/1, get_first_result/1]).
-export_type([language/0, location/0, geocoding_params/0, location_list/0]).
-type language() :: english |
german |
french |
spanish |
italian |
portuguese |
russian |
turkish |
hindi.
-type location() :: {location,
float(),
float(),
integer(),
binary(),
float(),
binary(),
binary(),
integer(),
gleam@option:option(integer()),
gleam@option:option(list(binary())),
gleam@option:option(binary()),
gleam@option:option(binary()),
gleam@option:option(binary()),
gleam@option:option(binary()),
gleam@option:option(integer()),
gleam@option:option(integer()),
gleam@option:option(integer()),
gleam@option:option(integer())}.
-type geocoding_params() :: {geocoding_params, binary(), integer(), language()}.
-type location_list() :: {location_list, gleam@option:option(list(location()))}.
-spec location_to_position(location()) -> sunny@position:position().
location_to_position(Location) ->
{position, erlang:element(2, Location), erlang:element(3, Location)}.
-spec params(binary()) -> geocoding_params().
params(Name) ->
{geocoding_params, Name, 10, english}.
-spec set_count(geocoding_params(), integer()) -> geocoding_params().
set_count(Params, Count) ->
erlang:setelement(3, Params, gleam@int:clamp(Count, 1, 100)).
-spec set_language(geocoding_params(), language()) -> geocoding_params().
set_language(Params, Language) ->
erlang:setelement(4, Params, Language).
-spec language_to_country_code(language()) -> binary().
language_to_country_code(Lang) ->
case Lang of
english ->
<<"en"/utf8>>;
german ->
<<"de"/utf8>>;
french ->
<<"fr"/utf8>>;
spanish ->
<<"es"/utf8>>;
italian ->
<<"it"/utf8>>;
portuguese ->
<<"pt"/utf8>>;
russian ->
<<"ru"/utf8>>;
turkish ->
<<"tr"/utf8>>;
hindi ->
<<"hi"/utf8>>
end.
-spec geocoding_params_to_params_list(geocoding_params()) -> list(sunny@internal@utils:request_parameter()).
geocoding_params_to_params_list(Params) ->
[{request_parameter, <<"name"/utf8>>, erlang:element(2, Params)},
{request_parameter,
<<"count"/utf8>>,
gleam@int:to_string(erlang:element(3, Params))},
{request_parameter,
<<"language"/utf8>>,
begin
_pipe = erlang:element(4, Params),
language_to_country_code(_pipe)
end},
{request_parameter, <<"format"/utf8>>, <<"json"/utf8>>}].
-spec get_request(sunny@internal@client:client(), geocoding_params()) -> gleam@http@request:request(binary()).
get_request(Client, Params) ->
Params@1 = case erlang:element(3, Params) of
C when (C > 100) orelse (C < 1) ->
set_count(Params, C);
_ ->
Params
end,
_pipe@1 = sunny@internal@utils:get_final_url(
erlang:element(2, Client),
<<"geocoding"/utf8>>,
erlang:element(3, Client),
<<"/search"/utf8>>,
erlang:element(4, Client),
begin
_pipe = Params@1,
geocoding_params_to_params_list(_pipe)
end
),
sunny@internal@utils:get_request(_pipe@1).
-spec locations_from_json(binary()) -> {ok, list(location())} |
{error, sunny@errors:sunny_error()}.
locations_from_json(Json_string) ->
Geocoding_decoder = gleam@dynamic:decode1(
fun(Field@0) -> {location_list, Field@0} end,
gleam@dynamic:optional_field(
<<"results"/utf8>>,
gleam@dynamic:list(
sunny@internal@utils:decode18(
fun(Field@0, Field@1, Field@2, Field@3, Field@4, Field@5, Field@6, Field@7, Field@8, Field@9, Field@10, Field@11, Field@12, Field@13, Field@14, Field@15, Field@16, Field@17) -> {location, Field@0, Field@1, Field@2, Field@3, Field@4, Field@5, Field@6, Field@7, Field@8, Field@9, Field@10, Field@11, Field@12, Field@13, Field@14, Field@15, Field@16, Field@17} end,
gleam@dynamic:field(
<<"latitude"/utf8>>,
fun gleam@dynamic:float/1
),
gleam@dynamic:field(
<<"longitude"/utf8>>,
fun gleam@dynamic:float/1
),
gleam@dynamic:field(<<"id"/utf8>>, fun gleam@dynamic:int/1),
gleam@dynamic:field(
<<"name"/utf8>>,
fun gleam@dynamic:string/1
),
gleam@dynamic:field(
<<"elevation"/utf8>>,
fun gleam@dynamic:float/1
),
gleam@dynamic:field(
<<"feature_code"/utf8>>,
fun gleam@dynamic:string/1
),
gleam@dynamic:field(
<<"country_code"/utf8>>,
fun gleam@dynamic:string/1
),
gleam@dynamic:field(
<<"country_id"/utf8>>,
fun gleam@dynamic:int/1
),
gleam@dynamic:optional_field(
<<"population"/utf8>>,
fun gleam@dynamic:int/1
),
gleam@dynamic:optional_field(
<<"postcodes"/utf8>>,
gleam@dynamic:list(fun gleam@dynamic:string/1)
),
gleam@dynamic:optional_field(
<<"admin1"/utf8>>,
fun gleam@dynamic:string/1
),
gleam@dynamic:optional_field(
<<"admin2"/utf8>>,
fun gleam@dynamic:string/1
),
gleam@dynamic:optional_field(
<<"admin3"/utf8>>,
fun gleam@dynamic:string/1
),
gleam@dynamic:optional_field(
<<"admin4"/utf8>>,
fun gleam@dynamic:string/1
),
gleam@dynamic:optional_field(
<<"admin1_id"/utf8>>,
fun gleam@dynamic:int/1
),
gleam@dynamic:optional_field(
<<"admin2_id"/utf8>>,
fun gleam@dynamic:int/1
),
gleam@dynamic:optional_field(
<<"admin3_id"/utf8>>,
fun gleam@dynamic:int/1
),
gleam@dynamic:optional_field(
<<"admin4_id"/utf8>>,
fun gleam@dynamic:int/1
)
)
)
)
),
_pipe = gleam@json:decode(Json_string, Geocoding_decoder),
_pipe@1 = gleam@result:map_error(_pipe, fun(X) -> {decode_error, X} end),
_pipe@2 = gleam@result:map(
_pipe@1,
fun(Locations_maybe) -> case Locations_maybe of
{location_list, {some, Locations}} ->
{ok, Locations};
_ ->
{error,
{api_error,
{no_results_error,
<<"Geocoding search gave no results"/utf8>>}}}
end end
),
gleam@result:flatten(_pipe@2).
-spec get_result(binary()) -> {ok, list(location())} |
{error, sunny@errors:sunny_error()}.
get_result(Response_body) ->
locations_from_json(Response_body).
-spec get_first_result(binary()) -> {ok, location()} |
{error, sunny@errors:sunny_error()}.
get_first_result(Response_body) ->
gleam@result:'try'(
get_result(Response_body),
fun(Locations) -> case Locations of
[Head | _] ->
{ok, Head};
[] ->
{error,
{sunny_internal_error,
{internal_error,
<<"`get_result` gave empty list instead of error."/utf8>>}}}
end end
).
-spec decoding_helper(
gleam@dict:dict(integer(), KWQ),
integer(),
list(KWQ),
integer()
) -> list(KWQ).
decoding_helper(D, N, L, Max) ->
case N of
N@1 when N@1 >= Max ->
L;
N@2 ->
L@1 = lists:append(L, [case gleam@dict:get(D, N@2) of
{ok, V} ->
V;
{error, _} ->
erlang:error(#{gleam_error => panic,
message => <<"This shouldn't happen."/utf8>>,
module => <<"sunny/api/geocoding"/utf8>>,
function => <<"decoding_helper"/utf8>>,
line => 242})
end]),
decoding_helper(D, N@2 + 1, L@1, Max)
end.