1:- module(bitrix24_rest, [
    2          api_call/4,
    3          api_call/5
    4      ]).    5
    6:- use_module(bitrix24_auth).    7:- use_module(bitrix24_request).    8
    9api_call(Provider, Method, Params, Result) :-
   10    call(Provider:default_context(ContextRef)),
   11    api_call(Provider, ContextRef, Method, Params, Result).
   12
   13api_call(Provider, ContextRef, Method, Params, Result) :-
   14    api_call_once(Provider, ContextRef, Method, Params, Result, false).
   15
   16api_call_once(Provider, ContextRef, Method, Params, Result, Retried) :-
   17    bitrix24_auth:check_context(Provider, ContextRef, Context),
   18    endpoint_url(Context.client_endpoint, Method, Url),
   19    Payload = json([auth=Context.access_token | Params]),
   20    bitrix24_request:post(Url, Payload, Response, []),
   21    normalize_response(Provider, ContextRef, Method, Params, Response, Result, Retried).
   22
   23normalize_response(Provider, ContextRef, Method, Params, Response, Result, false) :-
   24    bitrix_error(Response, expired_token, _Description),
   25    !,
   26    bitrix24_auth:refresh_context(Provider, ContextRef, _),
   27    api_call_once(Provider, ContextRef, Method, Params, Result, true).
   28normalize_response(_Provider, _ContextRef, Method, _Params, Response, _Result, _Retried) :-
   29    bitrix_error(Response, Code, Description),
   30    !,
   31    throw(error(bitrix24_api_error(Method, Code, Description, Response), _)).
   32normalize_response(_Provider, _ContextRef, _Method, _Params, Response, Response, _Retried).
   33
   34bitrix_error(Response, Code, Description) :-
   35    is_list(Response),
   36    memberchk(error=Code0, Response),
   37    normalize_code(Code0, Code),
   38    ( memberchk(error_description=Description, Response)
   39    -> true
   40    ; Description = ''
   41    ).
   42
   43normalize_code(Code, Normalized) :-
   44    atom(Code),
   45    !,
   46    downcase_atom(Code, Normalized).
   47normalize_code(Code, Normalized) :-
   48    string(Code),
   49    !,
   50    string_lower(Code, Lower),
   51    atom_string(Normalized, Lower).
   52normalize_code(Code, Code).
   53
   54endpoint_url(ClientEndpoint, Method, Url) :-
   55    ( sub_atom(ClientEndpoint, _, 1, 0, '/')
   56    -> atom_concat(ClientEndpoint, Method, Url)
   57    ;  format(atom(Url), '~w/~w', [ClientEndpoint, Method])
   58    )