<commit_before>%%%-----------------------------------------------------------------------------
%%% @author <NAME> <<EMAIL>>
%%% @doc
%%% VFFOV REST API
%%% @end
%%% Created : 1 Aug 2014 by tgrk <<EMAIL>>
%%%-----------------------------------------------------------------------------
-module(vffov_api).
-behaviour(elli_handler).

%% API
-export([handle/2, handle_event/3]).

%%%============================================================================
%%% API
%%%============================================================================
handle(Req, _Args) ->
    try
        Path = elli_request:path(Req),
        case elli_request:method(Req) of
            'GET' ->
                get(Path, Req);
            'POST' ->
                post(Path, Req);
            'OPTIONS' ->
                options(Path, Req)
        end
    catch
        _Class:Reason ->
            vffov_utils:verbose(error, "Unable to handle API request - ~p!",
                                [Reason]),
            return(500, <<"Internal error">>)
    end.

handle_event(_, _, _) ->
    ok.

%%%============================================================================
%%% REST API
%%%============================================================================
get([<<"stream">>], Req) ->
    ok = vffov_notify_server:add_client(elli_request:chunk_ref(Req)),
    {chunk, [{<<"Content-Type">>, <<"text/event-stream">>}]};
get([<<"queue">>], _Req) ->
    case vffov:queue() of
        []        -> return_json({[]});
        [{[],[]}] -> return_json({[]});
        Queue     ->
            L = queue:to_list(Queue),
            io:format("debug: queue_list=~p~n", [L]),
            return_json(<<"TODO: display queue">>)
    end;
get([], _Req) ->
    Payload = lists:map(fun ({K,V}) ->
                                {K, list_to_binary(V)}
                        end, vffov:status()),
    return_json({Payload});
get([<<"plugins">>], _Req) ->
    {ok, Getpocket} = application:get_env(vffov, enable_getpocket),
    {ok, Youtube} = application:get_env(vffov, enable_youtube),
    return_json({[{<<"getpocket">>, Getpocket},
                  {<<"youtube">>,   Youtube}]});
get(_Path, _Req) ->
    return_error(not_found).

post([<<"download">>], Req) ->
    Args = elli_request:body_qs(Req),
    case proplists:get_value(<<"url">>, Args, <<>>) of
        <<>> -> return_error(bad_request);
        Url  ->
            vffov:download(binary_to_list(Url)),
            return_json(<<"downloading">>)
    end;
post(_Path, _Req) ->
    return_error(not_found).

options(_Path, _Req) ->
    {200,
     [{"Access-Control-Allow-Origin", "*"},
      {"Access-Control-Allow-Methods", "GET, POST, OPTIONS"},
      {"Access-Control-Allow-Headers", "Authorization, Content-Type"},
      {"Access-Control-Allow-Credentials", "X-PINGOTHER"}],
     <<"">>}.

%%%============================================================================
%%% Internal functions
%%%============================================================================
return_json(Struct) ->
    return(200, jiffy:encode(Struct)).

return_error(not_found) ->
    return(404, <<"Not found">>);
return_error(bad_request) ->
    return(400, <<"Bad request">>).

return(Code, Body) ->
    {Code,
     [{<<"Content-Type">>, <<"application/json">>},
      {<<"Access-Control-Allow-Origin">>, <<"*">>}
     ],
     Body
    }.
<commit_msg>Implement HTTP API for getting queue and download based on JSON request<commit_after>%%%-----------------------------------------------------------------------------
%%% @author <NAME> <<EMAIL>>
%%% @doc
%%% VFFOV REST API
%%% @end
%%% Created : 1 Aug 2014 by tgrk <<EMAIL>>
%%%-----------------------------------------------------------------------------
-module(vffov_api).
-behaviour(elli_handler).

%% API
-export([handle/2, handle_event/3]).

%%%============================================================================
%%% API
%%%============================================================================
handle(Req, _Args) ->
    try
        Path = elli_request:path(Req),
        case elli_request:method(Req) of
            'GET' ->
                get(Path, Req);
            'POST' ->
                post(Path, Req);
            'OPTIONS' ->
                options(Path, Req)
        end
    catch
        _Class:Reason ->
            vffov_utils:verbose(error, "Unable to handle API request - ~p!",
                                [Reason]),
            return(500, <<"Internal error">>)
    end.

handle_event(_, _, _) ->
    ok.

%%%============================================================================
%%% REST API
%%%============================================================================
get([<<"stream">>], Req) ->
    ok = vffov_notify_server:add_client(elli_request:chunk_ref(Req)),
    {chunk, [{<<"Content-Type">>, <<"text/event-stream">>}]};
get([<<"queue">>], _Req) ->
    case vffov:queue() of
        []        -> return_json({[]});
        [{[],[]}] -> return_json({[]});
        Queue     ->
            JsonStruct = lists:map(fun ([Item]) ->
                                           {[{url, list_to_binary(Item)}]}
                                   end, queue:to_list(Queue)),
            return_json(JsonStruct)
    end;
get([], _Req) ->
    Payload = lists:map(fun ({K,V}) ->
                                {K, list_to_binary(V)}
                        end, vffov:status()),
    return_json({Payload});
get([<<"plugins">>], _Req) ->
    {ok, Getpocket} = application:get_env(vffov, enable_getpocket),
    {ok, Youtube} = application:get_env(vffov, enable_youtube),
    return_json({[{<<"getpocket">>, Getpocket},
                  {<<"youtube">>,   Youtube}]});
get(_Path, _Req) ->
    return_error(not_found).

%%TODO: plugins api?
post([<<"download">>], Req) ->
    try
        Args = elli_request:body_qs(Req),
        case proplists:is_defined(<<"url">>, Args) of
            true ->
                case proplists:get_value(<<"url">>, Args, <<>>) of
                    <<>> ->
                        return_error(bad_request);
                    Url  ->
                        vffov:download(binary_to_list(Url)),
                        return_json(<<"ok">>)
                end;
            false ->
                vffov:download(binary_to_list(elli_request:body(Req))),
                return_json(<<"ok">>)
        end
    catch
    _:Reason ->
            vffov_utils:verbose(error, "Unable to process API request: ~p",
                                [Reason]),
            return_error(bad_request)
    end;
post(_Path, _Req) ->
    return_error(not_found).

options(_Path, _Req) ->
    {200,
     [{"Access-Control-Allow-Origin", "*"},
      {"Access-Control-Allow-Methods", "GET, POST, OPTIONS"},
      {"Access-Control-Allow-Headers", "Authorization, Content-Type"},
      {"Access-Control-Allow-Credentials", "X-PINGOTHER"}],
     <<"">>}.

%%%============================================================================
%%% Internal functions
%%%============================================================================
return_json(Struct) ->
    return(200, jiffy:encode(Struct)).

return_error(not_found) ->
    return(404, <<"Not found">>);
return_error(bad_request) ->
    return(400, <<"Bad request">>).

return(Code, Body) ->
    {Code,
     [{<<"Content-Type">>, <<"application/json">>},
      {<<"Access-Control-Allow-Origin">>, <<"*">>}
     ],
     Body
    }.

{'fraction_non_alphanumeric': 0.33068747477465354, 'fraction_numerical': 0.005919547961792009, 'mean_word_length': 2.299600532623169, 'pattern_counts': {'":': 0, '<': 99, '<?xml version=': 0, '>': 151, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4847548', 'n_tokens_mistral': 2219, 'n_tokens_neox': 2088, 'n_words': 352}