Skip to content

Instantly share code, notes, and snippets.

@wdshin
Created June 25, 2021 06:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wdshin/9641444bf3d7cb091b5e869cff8667f4 to your computer and use it in GitHub Desktop.
Save wdshin/9641444bf3d7cb091b5e869cff8667f4 to your computer and use it in GitHub Desktop.
Erlang 코드 맞보기 , SNS 에서 유저를 follow 하는 Request 처리
%%%-------------------------------------------------------------------
%%% @author 신원동 <wdshin@CTO-Wondong-Shin.local>
%%% @copyright (C) 2015, 신원동
%%% @doc
%%%
%%% @end
%%% Created : 22 Oct 2015 by 신원동 <wdshin@CTO-Wondong-Shin.local>
%%%-------------------------------------------------------------------
-module(v1_user_follow).
-include("common.hrl").
%%-export([req/3]).
-include("fa.hrl").
%% API
-export([init/3,service_available/2]).
-export([allowed_methods/2,known_methods/2]).
-export([content_types_provided/2,content_types_accepted/2]).
-export([is_authorized/2,forbidden/2,resource_exists/2]).
-export([delete_resource/2, delete_completed/2]).
-export([handle_html/2]).
-export([handle_json/2]).
-export([handle_text/2]).
-export([process_post/2,handle_post/4,handle_proplists/3]).
-export([multiple_choices/2]).
%%%===================================================================
%%% API
%%%===================================================================
init(_Transport, _Req, []) ->
{upgrade, protocol, cowboy_rest}.
%% 서비스 사용 가능 상태
service_available(Req, Opts) ->
{true, Req, Opts}.
known_methods(Req, State) ->
{[<<"PUT">>, <<"POST">>,<<"DELETE">>,<<"GET">>], Req, State}.
allowed_methods(Req, State) ->
{[<<"PUT">>, <<"POST">>,<<"DELETE">>,<<"GET">>], Req, State}.
content_types_provided(Req, State) ->
{[
{{<<"application">>, <<"json">>, '*'}, handle_json},
{{<<"text">>, <<"html">>, '*'}, handle_html},
{{<<"text">>, <<"plain">>, '*'}, handle_text}
],Req, State}.
content_types_accepted(Req, State) ->
{[
{{<<"application">>, <<"json">>, '*' }, process_post}
],
Req, State}.
%% 인증처리 실패 응답 : 401 Unauthorized
is_authorized(Req, State) ->
f_auth:is_authorized(Req, State).
forbidden(Req, State) ->
%% Assume the users have access to everything (default value)
{false, Req, State}.
resource_exists(Req, State = #resource{method=_Method} ) -> %% Method =:= <<"GET">> <<"DELETE">> <<"PUT">>
f_resource:exists(Req, State , user_id ).
delete_resource(Req,State = #resource{user_id=SessionUserID,contents=Contents,error_code=ErrCode}) ->
try
case ErrCode of
undefined ->
{UserID} = Contents,
R = f_user_follow:stop(SessionUserID,UserID),
Result = [ { <<"user_id">> , UserID },
{ <<"stop_follow">> , m_conv:any_to_binary(R) } ],
Response = [
{ <<"result_code">> , ?RESULT_OK },
{ <<"result_msg">> , <<"">> },
{ <<"result_data">> , Result }
],
Ret = m_json:safe_encode(Response),
v1_common:handle_response(true,Ret,Req,State);
_ ->
throw({common_error,ErrCode})
end
catch
throw:Exception ->
v1_common:handle_exception(Exception,Req,State)
end.
delete_completed(Req, State) ->
{ true, Req, State }.
process_post(Req, State) ->
v1_common:process_post(Req, State, ?MODULE, handle_post ).
multiple_choices(Req,State = #resource{method=Method,user_id=SessionUserID,contents=Contents,error_code=ErrCode})
when Method == <<"POST">> orelse Method == <<"PUT">> orelse Method == <<"GET">> orelse Method == <<"DELETE">> ->
{ false, Req, State };%% false returns 200 ,
multiple_choices(Req,State ) ->
{ true, Req, State }. %% true returns 300
handle_html(Req, State) ->
v1_common:handle_proplists(Req, State, ?MODULE, handle_proplists ).
handle_text(Req, State) ->
v1_common:handle_proplists(Req, State, ?MODULE, handle_proplists ).
handle_json(Req, State) ->
v1_common:handle_proplists(Req, State, ?MODULE, handle_proplists ).
handle_post(Req,_,Body,State) ->
handle_proplists(Req,Body,State).
%%--------------------------------------------------------------------
%% @doc
%% @spec
%% @end
%%--------------------------------------------------------------------
%%%===================================================================
%%% Internal functions
%%%===================================================================
handle_proplists(Req,_,State = #resource{method=Method,error_code=ErrCode}) when ErrCode =/= undefined ->
case Method of
<<"GET">> -> v1_common:handle_exception(get,{common_error,ErrCode},Req,State);
_ -> v1_common:handle_exception({common_error,ErrCode},Req,State)
end;
handle_proplists(Req,PropLists,State = #resource{method= <<"GET">>,user_id=SessionUserID,locale=Locale,contents=Contents}) ->
%%m_logger:log("~p ~p GET ~p ",[?MODULE,?LINE,SessionUserID]),
try
{UserID} = Contents,
case f_user_block_user:is_block_user(SessionUserID, UserID) of
true ->
throw({common_error,?OBJECT_NOT_FOUND});%% TODO USER_BLOCKED_YOU
_ ->
noop
end,
case f_user_block_user:is_block_user(UserID, SessionUserID) of
true ->
throw({common_error,?OBJECT_NOT_FOUND});%% TODO USER_BLOCKED_YOU
_ ->
noop
end,
{_Code,Params} = v1_common:make_params_detector([],
[{<<"paging_id">>,m_uuid:v1(binary)},{<<"limit">>,10},{<<"list">>,<<"followers">>},{<<"mutual_page_limit">>,5}],
PropLists),
[ PagingID , Limit , ListMode , MutualPageLimit ] = Params,
case ListMode of
<<"follower">> ->
R = f_user_follow:list_followers(SessionUserID,UserID,PagingID,Limit,MutualPageLimit),
Result = [ { <<"followers">> , R } ];
<<"following">> ->
R = f_user_follow:list_followings(SessionUserID,UserID,PagingID,Limit,MutualPageLimit),
Result = [ { <<"followings">> , R } ];
_ ->
R = f_user_follow:list_followers(SessionUserID,UserID,PagingID,Limit,MutualPageLimit),
Result = [ { <<"followers">> , R } ]
end,
Response = [
{ <<"result_code">> , ?RESULT_OK },
{ <<"result_msg">> , <<"">> },
{ <<"result_data">> , Result }
],
Ret = m_json:safe_encode(Response),
v1_common:handle_response(true,Ret,Req,State)
catch
throw:Exception ->
v1_common:handle_exception(get,Exception,Req,State)
end;
handle_proplists(Req,PropLists,State = #resource{method= <<"PUT">>,user_id=SessionUserID,contents=Contents,locale=Locale,error_code=ErrCode}) ->
try
{UserID} = Contents,
if SessionUserID == UserID ->
throw({common_error,?PARAMS_ERROR});
true ->
noop
end,
case f_user_block_user:is_block_user(SessionUserID, UserID) of
true ->
throw({common_error,?OBJECT_NOT_FOUND});%% TODO USER_BLOCKED_YOU
_ ->
noop
end,
case f_user_block_user:is_block_user(UserID, SessionUserID) of
true ->
throw({common_error,?OBJECT_NOT_FOUND});%% TODO USER_BLOCKED_YOU
_ ->
noop
end,
{_Code,Params} = v1_common:make_params_detector([],
[{<<"follow_post">>,true}],
PropLists),
[ FollowPost0 ] = Params,
m_logger:log("~p ~p SessionUserID ~p UserID ~p FollowPost0 ~p ",[?MODULE,?LINE,SessionUserID,UserID,FollowPost0]),
bq_api_call:new(SessionUserID,<<"v1_user_follow">>,Locale),
R = f_user_follow:start(SessionUserID,UserID),
case R of
ok ->
%%m_logger:log("~p ~p SessionUserID ~p UserID ~p NEW FOLLOW force FollowPost true ",[?MODULE,?LINE,SessionUserID,UserID]),
FollowPost = true;
_ ->
FollowPost = FollowPost0
end,
%%m_logger:log("~p ~p SessionUserID ~p UserID ~p FollowPost ~p ",[?MODULE,?LINE,SessionUserID,UserID,FollowPost]),
FollowingInfo = db_user_follow:get_following(SessionUserID,UserID,[user_id,following_user_id,is_following_post]),
OldFollowingPost = m_kv:get_bool_default(is_following_post,FollowingInfo,true),
if OldFollowingPost =/= FollowPost ->
f_user_follow:follow_post(SessionUserID,UserID,FollowPost),
NewFollowingPost = FollowPost;
true ->
NewFollowingPost = OldFollowingPost
end,
SelectFields = [user_id, screen_name,profile,status,page_like_list,type],
UserInfo = db_user:get(UserID,SelectFields),
MyLikes = db_user:get_page_likes(SessionUserID),
MyLikesSet = sets:from_list(MyLikes),
UserLikes = m_kv:get_list(page_like_list,UserInfo),
UserLikesSet = sets:from_list(UserLikes),
MutualLikeSet = sets:intersection(MyLikesSet,UserLikesSet),
MutualCount = sets:size(MutualLikeSet),
User =
[
{<<"user_id">>, UserID },
{<<"screen_name">> , m_kv:get_binary(screen_name,UserInfo) },
{<<"profile">> , m_kv:get_binary(profile,UserInfo) },
{<<"status">> , m_kv:get_integer(status,UserInfo) },
{<<"type">> , m_kv:get_integer(type,UserInfo) }
] ,
Result = [ { <<"user">> , User },
{ <<"is_following_post">> , NewFollowingPost },
{ <<"mutual_like_count">> , MutualCount },
{ <<"follow">> , m_conv:any_to_binary(R) } ],
Response = [
{ <<"result_code">> , ?RESULT_OK },
{ <<"result_msg">> , <<"">> },
{ <<"result_data">> , Result }
],
Ret = m_json:encode(Response),
v1_common:handle_response(true,Ret,Req,State)
catch
throw:Exception ->
v1_common:handle_exception(Exception,Req,State)
end;
handle_proplists(Req,PropLists,State = #resource{method= <<"POST">> ,user_id=SessionUserID,contents=Contents,locale=Locale,error_code=ErrCode}) ->
try
{UserID} = Contents,
if SessionUserID == UserID ->
throw({common_error,?PARAMS_ERROR});
true ->
noop
end,
case f_user_block_user:is_block_user(SessionUserID, UserID) of
true ->
throw({common_error,?OBJECT_NOT_FOUND});%% TODO USER_BLOCKED_YOU
_ ->
noop
end,
case f_user_block_user:is_block_user(UserID, SessionUserID) of
true ->
throw({common_error,?OBJECT_NOT_FOUND});%% TODO USER_BLOCKED_YOU
_ ->
noop
end,
{_Code,Params} = v1_common:make_params_detector([],
[{<<"follow_post">>,true}],
PropLists),
[ FollowPost0 ] = Params,
m_logger:log("~p ~p SessionUserID ~p UserID ~p FollowPost0 ~p ",[?MODULE,?LINE,SessionUserID,UserID,FollowPost0]),
bq_api_call:new(SessionUserID,<<"v1_user_follow">>,Locale),
R = f_user_follow:start(SessionUserID,UserID),
case R of
ok ->
m_logger:log("~p ~p SessionUserID ~p UserID ~p NEW FOLLOW force FollowPost true ",[?MODULE,?LINE,SessionUserID,UserID]),
FollowPost = true;
_ ->
FollowPost = FollowPost0
end,
m_logger:log("~p ~p SessionUserID ~p UserID ~p FollowPost ~p ",[?MODULE,?LINE,SessionUserID,UserID,FollowPost]),
FollowingInfo = db_user_follow:get_following(SessionUserID,UserID,[user_id,following_user_id,is_following_post]),
OldFollowingPost = m_kv:get_bool_default(is_following_post,FollowingInfo,true),
if OldFollowingPost =/= FollowPost ->
f_user_follow:follow_post(SessionUserID,UserID,FollowPost),
NewFollowingPost = FollowPost;
true ->
NewFollowingPost = OldFollowingPost
end,
SelectFields = [user_id, screen_name,profile,status,page_like_list,type],
UserInfo = db_user:get(UserID,SelectFields),
MyLikes = db_user:get_page_likes(SessionUserID),
MyLikesSet = sets:from_list(MyLikes),
UserLikes = m_kv:get_list(page_like_list,UserInfo),
UserLikesSet = sets:from_list(UserLikes),
MutualLikeSet = sets:intersection(MyLikesSet,UserLikesSet),
MutualCount = sets:size(MutualLikeSet),
User =
[
{<<"user_id">>, UserID },
{<<"screen_name">> , m_kv:get_binary(screen_name,UserInfo) },
{<<"profile">> , m_kv:get_binary(profile,UserInfo) },
{<<"status">> , m_kv:get_integer(status,UserInfo) },
{<<"type">> , m_kv:get_integer(type,UserInfo) }
] ,
Result = [ { <<"user">> , User },
{ <<"mutual_like_count">> , MutualCount },
{ <<"follow">> , m_conv:any_to_binary(R) } ],
Response = [
{ <<"result_code">> , ?RESULT_OK },
{ <<"result_msg">> , <<"">> },
{ <<"result_data">> , Result }
],
Ret = m_json:encode(Response),
v1_common:handle_response(true,Ret,Req,State)
catch
throw:Exception ->
v1_common:handle_exception(Exception,Req,State)
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment