kvs_feed.erl 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. -module(kvs_feed).
  2. -author('Maxim Sokhatsky').
  3. -author('Andrii Zadorozhnii').
  4. -author('Alexander Kalenuk').
  5. -copyright('Synrc Research Center, s.r.o.').
  6. -compile(export_all).
  7. -include_lib("kvs/include/feeds.hrl").
  8. -include_lib("kvs/include/users.hrl").
  9. -include_lib("kvs/include/groups.hrl").
  10. -include_lib("kvs/include/feed_state.hrl").
  11. -include_lib("kvs/include/log.hrl").
  12. -define(CACHED_ENTRIES, 20).
  13. create() ->
  14. FId = kvs:next_id("feed", 1),
  15. ok = kvs:put(#feed{id = FId} ),
  16. FId.
  17. add_like(Fid, Eid, Uid) ->
  18. Write_one_like = fun(Next) ->
  19. Self_id = kvs:next_id("one_like", 1),
  20. kvs:put(#one_like{ % add one like
  21. id = Self_id,
  22. user_id = Uid,
  23. entry_id = Eid,
  24. feed_id = Fid,
  25. created_time = now(),
  26. next = Next
  27. }),
  28. Self_id
  29. end,
  30. % add entry - like
  31. case kvs:get(entry_likes, Eid) of
  32. {ok, ELikes} ->
  33. kvs:put(ELikes#entry_likes{
  34. one_like_head = Write_one_like(ELikes#entry_likes.one_like_head),
  35. total_count = ELikes#entry_likes.total_count + 1
  36. });
  37. {error, _} ->
  38. kvs:put(#entry_likes{
  39. entry_id = Eid,
  40. one_like_head = Write_one_like(undefined),
  41. total_count = 1
  42. })
  43. end,
  44. % add user - like
  45. case kvs:get(user_likes, Uid) of
  46. {ok, ULikes} ->
  47. kvs:put(ULikes#user_likes{
  48. one_like_head = Write_one_like(ULikes#user_likes.one_like_head),
  49. total_count = ULikes#user_likes.total_count + 1
  50. });
  51. {error, _} ->
  52. kvs:put(#user_likes{
  53. user_id = Uid,
  54. one_like_head = Write_one_like(undefined),
  55. total_count = 1
  56. })
  57. end.
  58. entries_count(Uid) ->
  59. case kvs:get(user_etries_count, Uid) of
  60. {ok, UEC} -> UEC#user_etries_count.entries;
  61. {error, _} -> 0 end.
  62. comments_count(Uid) ->
  63. case kvs:get(user_etries_count, Uid) of
  64. {ok, UEC} -> UEC#user_etries_count.comments;
  65. {error, _} -> 0 end.
  66. edit_entry(FeedId, EId, NewDescription) ->
  67. case kvs:get(entry,{EId, FeedId}) of
  68. {ok, OldEntry} ->
  69. NewEntryRaw = OldEntry#entry{description = NewDescription},
  70. NewEntry = feedformat:format(NewEntryRaw),
  71. kvs:put(NewEntry);
  72. {error, Reason}-> {error, Reason} end.
  73. like_list(undefined) -> [];
  74. like_list(Id) -> {ok, OneLike} = kvs:get(one_like, Id), [OneLike] ++ like_list(OneLike#one_like.next).
  75. like_list(undefined, _) -> [];
  76. like_list(_, 0) -> [];
  77. like_list(Id, N) -> {ok, OneLike} = kvs:get(one_like, Id), [OneLike] ++ like_list(OneLike#one_like.next, N-1).
  78. entry_likes(Entry_id) ->
  79. case kvs:get(entry_likes, Entry_id) of
  80. {ok, Likes} -> like_list(Likes#entry_likes.one_like_head);
  81. {error, _} -> [] end.
  82. entry_likes_count(Entry_id) ->
  83. case kvs:get(entry_likes, Entry_id) of
  84. {ok, Likes} -> Likes#entry_likes.total_count;
  85. {error, _} -> 0 end.
  86. user_likes_count(UserId) ->
  87. case kvs:get(user_likes, UserId) of
  88. {ok, Likes} -> Likes#user_likes.total_count;
  89. {error, _} -> 0 end.
  90. user_likes(UserId) ->
  91. case kvs:get(user_likes, UserId) of
  92. {ok, Likes} -> like_list(Likes#user_likes.one_like_head);
  93. {error, _} -> [] end.
  94. user_likes(UserId, {Page, PageAmount}) ->
  95. case kvs:get(user_likes, UserId) of
  96. {ok, Likes} -> lists:nthtail((Page-1)*PageAmount, like_list(Likes#user_likes.one_like_head, PageAmount*Page));
  97. {error, _} -> [] end.
  98. %% MQ API
  99. handle_notice([kvs_feed, _, Owner, entry, Eid, add],
  100. [#entry{feed_id=Fid, to={RouteType, _}}=Entry,_,_,_,_],
  101. #state{owner=Owner, feeds=Feeds} = S) ->
  102. case lists:keyfind(Fid,2,Feeds) of false -> skip;
  103. {_,_} ->
  104. EntryId = case Eid of new -> kvs:uuid(); _-> Eid end,
  105. E = Entry#entry{id = {EntryId, Fid}, entry_id = EntryId, feeds=[comments] },
  106. kvs:add(E),
  107. % todo: group entry counts should be counted for each feed
  108. case RouteType of group ->
  109. {ok, Group} = kvs:get(group, Owner),
  110. GE = Group#group.entries_count,
  111. error_logger:info_msg("count: ~p", [GE]),
  112. kvs:put(Group#group{entries_count = GE+1}),
  113. case kvs:get(group_subscription, {E#entry.from, Owner}) of
  114. {ok, Subs} -> SE = Subs#group_subscription.posts_count,
  115. kvs:put(Subs#group_subscription{posts_count = SE+1});
  116. {error,not_found} -> error_logger:info_msg("no group subscription found") end;
  117. _ -> skip end
  118. end,
  119. % self() ! {feed_refresh, Fid, ?CACHED_ENTRIES};
  120. {noreply, S};
  121. handle_notice([kvs_feed,_, Owner, entry, {_, Fid}, edit],
  122. #entry{entry_id=Eid}=Entry,
  123. #state{owner=Owner, feeds=Feeds}=S) ->
  124. case lists:keyfind(Fid,2,Feeds) of false -> skip;
  125. {_,_} -> case kvs:get(entry, {Eid, Fid}) of {error, not_found}-> skip;
  126. {ok, E} ->
  127. error_logger:info_msg("kvs_feed => Entry ~p updated in feed ~p", [Eid, Fid]),
  128. kvs:put(E#entry{description=Entry#entry.description,
  129. title = Entry#entry.title,
  130. media = Entry#entry.media,
  131. etc = Entry#entry.etc,
  132. type = Entry#entry.type}) end end,
  133. {noreply, S};
  134. handle_notice([kvs_feed,_, Owner, entry, {_,Fid}, delete],
  135. [#entry{id=Id, entry_id=Eid},_], #state{owner=Owner, feeds=Feeds} = State) ->
  136. case lists:keyfind(Fid,2,Feeds) of false -> skip;
  137. {_,_} -> error_logger:info_msg("REMOVE from FID ~p", [Fid]),kvs:remove(entry, Id) end,
  138. % self() ! {feed_refresh, FeedId, ?CACHED_ENTRIES};
  139. {noreply, State};
  140. handle_notice([kvs_feed, entry, {Eid, FeedId}, comment, Cid, add],
  141. [From, Parent, Content, Medias, _, _],
  142. #state{owner=Owner, feeds=Feeds} = State) ->
  143. HasFeed = lists:keyfind(FeedId,2,Feeds) /= false,
  144. if HasFeed ->
  145. [begin error_logger:info_msg("Comment: worker ~p entry ~p cid ",[Owner, Eid]),
  146. {_, CFid} = lists:keyfind(comments, 1, E#entry.feeds),
  147. error_logger:info_msg("Add comment to entry ~p~n----------------~n", [E#entry.id]),
  148. error_logger:info_msg("Comments feed id: ~p", [CFid]),
  149. error_logger:info_msg("Comment parent ~p", [Parent]),
  150. FeedId2 = case Parent of undefined -> CFid;
  151. Id ->
  152. case kvs:get(comment, {Parent, {E#entry.entry_id, E#entry.feed_id}}) of {error, not_found} -> error_logger:info_msg("NO PARENT COMMENT"),CFid;
  153. {ok, C} -> {_, PCFid} = lists:keyfind(comments, 1, C#comment.feeds), PCFid end
  154. end,
  155. error_logger:info_msg("Target feed id: ~p", [FeedId2]),
  156. EntryId = E#entry.entry_id,
  157. FullId = {Cid, {EntryId, E#entry.feed_id}},
  158. User = From,
  159. Comment = #comment{id = FullId,
  160. author_id = User,
  161. comment_id = Cid,
  162. entry_id = EntryId,
  163. feed_id = FeedId2, % entry commens or parent comment comments
  164. content = Content,
  165. media = Medias,
  166. creation_time = now(),
  167. feeds = [comments]},
  168. error_logger:info_msg("Comment ~p ready to put.", [Comment]),
  169. kvs:add(Comment)
  170. % kvs_comment:add(E#entry.feed_id, From, E#entry.entry_id, Parent, Cid, Content, Medias)
  171. end || E <- kvs:all_by_index(entry, entry_id, Eid)];
  172. true -> skip end,
  173. {noreply, State};
  174. handle_notice(["kvs_feed", "user", UId, "count_entry_in_statistics"] = Route,
  175. Message, #state{owner = Owner, type =Type} = State) ->
  176. error_logger:info_msg("queue_action(~p): count_entry_in_statistics: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),
  177. case kvs:get(user_etries_count, UId) of
  178. {ok, UEC} ->
  179. kvs:put(UEC#user_etries_count{entries = UEC#user_etries_count.entries+1 }),
  180. kvs_users:attempt_active_user_top(UId, UEC#user_etries_count.entries+1);
  181. {error, _} ->
  182. kvs:put(#user_etries_count{user_id = UId, entries = 1 }),
  183. kvs_users:attempt_active_user_top(UId, 1) end,
  184. {noreply, State};
  185. handle_notice(["kvs_feed", "user", UId, "count_comment_in_statistics"] = Route,
  186. Message, #state{owner = Owner, type =Type} = State) ->
  187. error_logger:info_msg("queue_action(~p): count_comment_in_statistics: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),
  188. case kvs:get(user_etries_count, UId) of
  189. {ok, UEC} -> kvs:put(UEC#user_etries_count{comments = UEC#user_etries_count.comments+1 });
  190. {error, _} -> kvs:put(#user_etries_count{ user_id = UId, comments = 1 }) end,
  191. {noreply, State};
  192. handle_notice(["kvs_feed","likes", _, _, "add_like"] = Route, % _, _ is here beacause of the same message used for comet update
  193. Message, #state{owner = Owner, type =Type} = State) ->
  194. error_logger:info_msg("queue_action(~p): add_like: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),
  195. {UId, E} = Message,
  196. {EId, FId} = E#entry.id,
  197. kvs_feed:add_like(FId, EId, UId),
  198. {noreply, State};
  199. handle_notice(_Route, _Message, State) ->
  200. %error_logger:error_msg("~p ===> Unknown FEED notice ~p", [State#state.owner, Route]),
  201. {noreply, State}.