-module(gliberapay). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -define(FILEPATH, "src/gliberapay.gleam"). -export([download_patrons_csv_request/1, parse_patrons_csv/1]). -export_type([patron/0, error/0, date/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. -type patron() :: {patron, date(), integer(), binary(), gleam@option:option(binary()), binary(), gleam@option:option(float()), binary()}. -type error() :: {invalid_csv_syntax, gsv:parse_error()} | missing_csv_header_row | {missing_csv_headers, list(binary())} | {invalid_value, binary()}. -type date() :: {date, integer(), integer(), integer()}. -file("src/gliberapay.gleam", 55). ?DOC( " Construct a HTTP request to download the public Liberapay patrons CSV for\n" " the given recipient.\n" "\n" " Once you have a response for the request you can parse the body with the\n" " `parse_patrons_csv` function.\n" ). -spec download_patrons_csv_request(binary()) -> gleam@http@request:request(binary()). download_patrons_csv_request(Recipient) -> _pipe = gleam@http@request:new(), _pipe@1 = gleam@http@request:set_host(_pipe, <<"liberapay.com"/utf8>>), gleam@http@request:set_path( _pipe@1, <<<<"/"/utf8, Recipient/binary>>/binary, "/patrons/public.csv"/utf8>> ). -file("src/gliberapay.gleam", 112). -spec optional_string(binary()) -> gleam@option:option(binary()). optional_string(S) -> case S of <<""/utf8>> -> none; _ -> {some, S} end. -file("src/gliberapay.gleam", 119). -spec parse_int(binary()) -> {ok, integer()} | {error, error()}. parse_int(Int) -> case gleam_stdlib:parse_int(Int) of {ok, I} -> {ok, I}; _ -> {error, {invalid_value, <<"invalid int: "/utf8, Int/binary>>}} end. -file("src/gliberapay.gleam", 126). -spec parse_amount(binary()) -> {ok, gleam@option:option(float())} | {error, error()}. parse_amount(Amount) -> case Amount of <<""/utf8>> -> {ok, none}; <<"private"/utf8>> -> {ok, none}; _ -> case gleam_stdlib:parse_float(Amount) of {ok, F} -> {ok, {some, F}}; _ -> case gleam_stdlib:parse_int(Amount) of {ok, I} -> {ok, {some, erlang:float(I)}}; _ -> {error, {invalid_value, <<"invalid float: "/utf8, Amount/binary>>}} end end end. -file("src/gliberapay.gleam", 141). -spec parse_date(binary()) -> {ok, date()} | {error, error()}. parse_date(Date) -> gleam@result:'try'( begin _pipe = gleam@string:split(Date, <<"-"/utf8>>), _pipe@1 = gleam@list:try_map(_pipe, fun gleam_stdlib:parse_int/1), gleam@result:map_error( _pipe@1, fun(_) -> {invalid_value, <<"invalid date: "/utf8, Date/binary>>} end ) end, fun(Numbers) -> case Numbers of [Year, Month, Day] -> {ok, {date, Year, Month, Day}}; _ -> {error, {invalid_value, <<"invalid date: "/utf8, Date/binary>>}} end end ). -file("src/gliberapay.gleam", 153). -spec pop_headers(list(list(binary()))) -> {ok, {list(binary()), list(list(binary()))}} | {error, error()}. pop_headers(Csv) -> gleam@result:'try'(case Csv of [First | Rest] -> {ok, {First, Rest}}; [] -> {error, missing_csv_header_row} end, fun(_use0) -> {Headers, Rest@1} = _use0, Headers_set = gleam@set:from_list(Headers), Missing = gleam@list:filter( [<<"pledge_date"/utf8>>, <<"patron_id"/utf8>>, <<"patron_username"/utf8>>, <<"patron_public_name"/utf8>>, <<"donation_currency"/utf8>>, <<"weekly_amount"/utf8>>, <<"patron_avatar_url"/utf8>>], fun(H) -> not gleam@set:contains(Headers_set, H) end ), case Missing of [] -> {ok, {Headers, Rest@1}}; _ -> {error, {missing_csv_headers, Missing}} end end). -file("src/gliberapay.gleam", 75). -spec extract_csv_patrons(list(list(binary()))) -> {ok, list(patron())} | {error, error()}. extract_csv_patrons(Csv) -> gleam@result:'try'( pop_headers(Csv), fun(_use0) -> {Headers, Rows} = _use0, Rows@1 = gleam@list:map( Rows, fun(Row) -> _pipe = gleam@list:zip(Headers, Row), maps:from_list(_pipe) end ), gleam@list:try_map( Rows@1, fun(Row@1) -> Get = fun(K) -> case gleam_stdlib:map_get(Row@1, K) of {ok, V} -> {ok, V}; _ -> {error, {invalid_value, <<"missing value for "/utf8, K/binary>>}} end end, gleam@result:'try'( Get(<<"pledge_date"/utf8>>), fun(Date) -> gleam@result:'try'( Get(<<"patron_id"/utf8>>), fun(Id) -> gleam@result:'try'( Get(<<"patron_username"/utf8>>), fun(Username) -> gleam@result:'try'( Get( <<"patron_public_name"/utf8>> ), fun(Name) -> gleam@result:'try'( Get( <<"donation_currency"/utf8>> ), fun(Currency) -> gleam@result:'try'( Get( <<"weekly_amount"/utf8>> ), fun(Amount) -> gleam@result:'try'( Get( <<"patron_avatar_url"/utf8>> ), fun( Avatar ) -> gleam@result:'try'( parse_date( Date ), fun( Date@1 ) -> gleam@result:'try'( parse_int( Id ), fun( Id@1 ) -> gleam@result:'try'( parse_amount( Amount ), fun( Amount@1 ) -> {ok, {patron, Date@1, Id@1, Username, optional_string( Name ), Currency, Amount@1, Avatar}} end ) end ) end ) end ) end ) end ) end ) end ) end ) end ) end ) end ). -file("src/gliberapay.gleam", 68). ?DOC( " Parse a Liberapay patrons CSV, as can be downloaded from the Liberapay, e.g.\n" " \n" "\n" " If you want to download this in Gleam see the `download_patrons_csv` function.\n" ). -spec parse_patrons_csv(binary()) -> {ok, list(patron())} | {error, error()}. parse_patrons_csv(Csv) -> _pipe = Csv, _pipe@1 = gsv:to_lists(_pipe), _pipe@2 = gleam@result:map_error( _pipe@1, fun(Field@0) -> {invalid_csv_syntax, Field@0} end ), gleam@result:'try'(_pipe@2, fun extract_csv_patrons/1).