diff --git a/src/http_front/api.erl b/src/http_front/api.erl index 85f52d7..af2f1d8 100644 --- a/src/http_front/api.erl +++ b/src/http_front/api.erl @@ -5,28 +5,64 @@ %% HTTP API %% -module(api). --export([search/3]). +-export([search/3, + today_top/3, + stats/3, + index/3]). -compile(export_all). -define(TEXT(Fmt, Args), lists:flatten(io_lib:format(Fmt, Args))). --define(MAX_FILE, 10). +-define(MAX_FILE, 3). +-define(CONTENT_TYPE, "Content-Type: application/json\r\n\r\n"). +% search?q=keyword search(SessionID, _Env, Input) -> - Res = case crawler_http:get_search_keyword(Input) of + Res = case http_common:get_search_keyword(Input) of [] -> "{\"error\":\"null input\", \"suggest\":\"api/search?q=keyword\"}"; Keyword -> do_search(Keyword) end, - mod_esi:deliver(SessionID, ["Content-Type: application/json\r\n\r\n", Res]). + mod_esi:deliver(SessionID, [?CONTENT_TYPE, Res]). +% today_top +today_top(SessionID, _Env, _Input) -> + Rets = http_cache:today_top(), + BodyList = format_search_result(Rets), + Body = ?TEXT("{\"results\":[~s]}", [BodyList]), + mod_esi:deliver(SessionID, [?CONTENT_TYPE, Body]). + +% index?q=hash +index(SessionID, _Env, Input) -> + Body = case http_common:get_view_hash(Input) of + [] -> + "{\"error\":\"invalid input\"}"; + Hash -> + format_view(Hash) + end, + mod_esi:deliver(SessionID, [?CONTENT_TYPE, Body]). + +stats(SessionID, _Env, _Input) -> + Response = format_stats_list(http_cache:stats()), + mod_esi:deliver(SessionID, [?CONTENT_TYPE, Response]). +%% do_search(Keyword) -> {Rets, Stats} = http_cache:search(Keyword), {_Found, Cost, Scanned} = Stats, - Tip = ?TEXT("{\"keyword\":\"~s\", \"found\":~p, \"cost\":~p,", [Keyword, Scanned, Cost div 1000]), + Tip = ?TEXT("{\"keyword\":\"~s\",\"found\":~p,\"cost\":~p,", [Keyword, Scanned, Cost div 1000]), BodyList = format_search_result(Rets), Body = ?TEXT("\"results\":[~s]}", [BodyList]), Tip ++ Body. +format_view(Hash) -> + case db_frontend:search_one(Hash) of + {} -> "{\"error\":\"not found\"}"; + Torrent -> + format_torrent_detail(Torrent) + end. + +format_torrent_detail(Torrent) -> + format_one_result(Torrent, true). + format_search_result([]) -> ""; format_search_result([First|Rest]) -> @@ -39,10 +75,13 @@ format_one_result({single, Hash, {Name, Length}, Announce, CTime}, ShowAll) -> format_one_result({multi, Hash, {Name, Files}, Announce, CTime}, ShowAll) -> format_one_result(Hash, Name, Files, Announce, CTime, ShowAll). +% {"hash":"abc", "name":"abc", "created_at":time, "req":count, "file_cnt":cnt, +% "files":[{"name":"abc", "size":size}]} format_one_result(Hash, Name, Files, Announce, CTime, ShowAll) -> - ?TEXT("{\"hash\":\"~s\", \"name\":\"~s\", \"created_at\":~p, \"req\":~p,", - [Hash, Name, CTime, Announce]) ++ - "\"files\":[" ++ format_files(Files, ShowAll) ++ "]}". + SortedFiles = http_common:sort_file_by_size(Files), + ?TEXT("{\"hash\":\"~s\",\"name\":\"~s\",\"created_at\":~p,\"req\":~p,\"file_cnt\":~p,", + [Hash, Name, CTime, Announce, length(Files)]) ++ + "\"files\":[" ++ format_files(SortedFiles, ShowAll) ++ "]}". format_files([], _) -> ""; @@ -51,7 +90,7 @@ format_files(Files, false) -> Max = ?MAX_FILE, Sub = case length(Files) >= Max of true -> - lists:sublist(Files, Max) ++ [{more, length(Files) - Max}]; + lists:sublist(Files, Max); false -> Files end, @@ -70,6 +109,21 @@ format_file({more, Len}) -> format_file({Name, Length}) -> ?TEXT("{\"name\":\"~s\",\"size\":~b}", [Name, Length]). +format_stats_list(Stats) -> + {TorSum, StatsList} = Stats, + ?TEXT("{\"total\":~p, \"stats\":[", [TorSum]) ++ + do_format_stats(StatsList) ++ "]}". + +do_format_stats([]) -> + ""; +do_format_stats([First|Rest]) -> + S = [format_stats(First)] ++ ["," ++ format_stats(Stats) || Stats <- Rest], + lists:flatten(S). + +format_stats({DaySec, Processed, RecvQuery, Updated, New}) -> + ?TEXT("{\"day_secs\":~p, \"recv\":~p, \"process\":~p, \"update\":~p, \"new\":~p}", + [DaySec, RecvQuery, Processed, Updated, New]). + %% test_search(Keyword) -> Filename = ?TEXT("search_~s.html", [Keyword]), diff --git a/src/http_front/crawler_http.erl b/src/http_front/crawler_http.erl index 8d15fa5..0b0f957 100644 --- a/src/http_front/crawler_http.erl +++ b/src/http_front/crawler_http.erl @@ -15,7 +15,6 @@ start/4, start/1, page_temp/0, - get_search_keyword/1, stop/0]). -record(state, {html_temp, httpid}). @@ -91,12 +90,3 @@ code_change(_, _, State) -> handle_info(_, State) -> {noreply, State}. -get_search_keyword(Input) -> - D = urldecode:decode(Input), - ReqList = httpd:parse_query(D), - case proplists:get_value("q", ReqList) of - undefined -> - ""; - Keyword -> - Keyword - end. diff --git a/src/http_front/http_common.erl b/src/http_front/http_common.erl new file mode 100644 index 0000000..fd63263 --- /dev/null +++ b/src/http_front/http_common.erl @@ -0,0 +1,30 @@ +%% +%% http_common.erl +%% Kevin Lynx +%% 07.22.2013 +%% +-module(http_common). +-export([get_search_keyword/1, + get_view_hash/1, + sort_file_by_size/1]). + +get_search_keyword(Input) -> + get_q_arg(Input). + +get_view_hash(Input) -> + get_q_arg(Input). + +get_q_arg(Input) -> + D = urldecode:decode(Input), + ReqList = httpd:parse_query(D), + case proplists:get_value("q", ReqList) of + undefined -> + ""; + Arg -> + Arg + end. + +sort_file_by_size(Files) -> + lists:sort(fun({_, L1}, {_, L2}) -> + L1 > L2 + end, Files). diff --git a/src/http_front/http_handler.erl b/src/http_front/http_handler.erl index e5e0f43..5f80d8c 100644 --- a/src/http_front/http_handler.erl +++ b/src/http_front/http_handler.erl @@ -17,7 +17,7 @@ -define(CONTENT_TYPE, "Content-Type: text/html\r\n\r\n"). search(SessionID, _Env, Input) -> - {K, Body} = case crawler_http:get_search_keyword(Input) of + {K, Body} = case http_common:get_search_keyword(Input) of [] -> {"", "invalid input"}; Key -> @@ -64,7 +64,7 @@ format_stats_list(Stats) -> simple_html("", Body). index(SessionID, _Env, Input) -> - Body = case get_index_hash(Input) of + Body = case http_common:get_view_hash(Input) of [] -> "invalid hash"; Hash -> @@ -73,14 +73,6 @@ index(SessionID, _Env, Input) -> Response = simple_html("", Body), mod_esi:deliver(SessionID, [?CONTENT_TYPE, Response]). -get_index_hash(Input) -> - case string:equal(string:substr(Input, 1, 2), "q=") of - true -> - string:substr(Input, 3); - false -> - [] - end. - simple_html(Key, Body) -> ?TEXT(crawler_http:page_temp(), [Key, Body]). @@ -111,9 +103,10 @@ format_one_result({multi, Hash, {Name, Files}, Announce, CTime}, ShowAll) -> format_one_result(Hash, Name, Files, Announce, CTime, ShowAll). format_one_result(Hash, Name, Files, Announce, CTime, ShowAll) -> + SortedFiles = http_common:sort_file_by_size(Files), ?TEXT("
  • ~s

    ", - [Hash, Name, format_files(Files, ShowAll)]) ++ + [Hash, Name, format_files(SortedFiles, ShowAll)]) ++ ?TEXT("

    Index at: ~s | File count: ~p | Query count: ~p Download

    ", [format_time_string(CTime), length(Files), Announce, format_magnet(Hash)]).