201 lines
5.5 KiB
Erlang
201 lines
5.5 KiB
Erlang
-module(logic_moderation).
|
|
-include("records.hrl").
|
|
|
|
-export([create_report/4,
|
|
get_reports/1,
|
|
get_reports_by_target/3,
|
|
resolve_report/3]).
|
|
|
|
-export([add_banned_word/2,
|
|
remove_banned_word/2,
|
|
list_banned_words/1]).
|
|
|
|
-export([check_content/1,
|
|
auto_moderate/1]).
|
|
|
|
-export([freeze_calendar/2,
|
|
unfreeze_calendar/2,
|
|
freeze_event/2,
|
|
unfreeze_event/2]).
|
|
|
|
-define(REPORT_THRESHOLD, 3).
|
|
|
|
%% ============ Жалобы =====================================
|
|
|
|
create_report(ReporterId, TargetType, TargetId, Reason) ->
|
|
case target_exists(TargetType, TargetId) of
|
|
true ->
|
|
case core_report:create(ReporterId, TargetType, TargetId, Reason) of
|
|
{ok, Report} ->
|
|
logic_notification:notify_admin(report_created, #{
|
|
report_id => Report#report.id,
|
|
target_type => TargetType,
|
|
target_id => TargetId,
|
|
reason => Reason
|
|
}),
|
|
check_auto_freeze(TargetType, TargetId),
|
|
{ok, Report};
|
|
Error ->
|
|
Error
|
|
end;
|
|
false ->
|
|
{error, target_not_found}
|
|
end.
|
|
|
|
get_reports(AdminId) ->
|
|
case admin_utils:is_admin(AdminId) of
|
|
true -> core_report:list_all();
|
|
false -> {error, access_denied}
|
|
end.
|
|
|
|
get_reports_by_target(AdminId, TargetType, TargetId) ->
|
|
case admin_utils:is_admin(AdminId) of
|
|
true -> core_report:list_by_target(TargetType, TargetId);
|
|
false -> {error, access_denied}
|
|
end.
|
|
|
|
resolve_report(AdminId, ReportId, Action)
|
|
when Action =:= reviewed; Action =:= dismissed ->
|
|
case admin_utils:is_admin(AdminId) of
|
|
true ->
|
|
case core_report:get_by_id(ReportId) of
|
|
{ok, Report} ->
|
|
case Report#report.status of
|
|
pending ->
|
|
core_report:update_status(ReportId, Action, AdminId);
|
|
_ ->
|
|
{error, already_resolved}
|
|
end;
|
|
Error ->
|
|
Error
|
|
end;
|
|
false ->
|
|
{error, access_denied}
|
|
end.
|
|
|
|
check_auto_freeze(TargetType, TargetId) ->
|
|
Count = core_report:get_count_by_target(TargetType, TargetId),
|
|
if
|
|
Count >= ?REPORT_THRESHOLD ->
|
|
auto_freeze(TargetType, TargetId);
|
|
true ->
|
|
ok
|
|
end.
|
|
|
|
auto_freeze(event, EventId) ->
|
|
case core_event:get_by_id(EventId) of
|
|
{ok, Event} when Event#event.status =:= active ->
|
|
core_event:update(EventId, [{status, frozen}]);
|
|
_ -> ok
|
|
end;
|
|
auto_freeze(calendar, CalendarId) ->
|
|
case core_calendar:get_by_id(CalendarId) of
|
|
{ok, Calendar} when Calendar#calendar.status =:= active ->
|
|
core_calendar:update(CalendarId, [{status, frozen}]);
|
|
_ -> ok
|
|
end;
|
|
auto_freeze(_, _) -> ok.
|
|
|
|
%% ============ Бан-лист ===================================
|
|
|
|
add_banned_word(AdminId, Word) ->
|
|
case admin_utils:is_admin(AdminId) of
|
|
true -> core_banned_words:add_banned_word(Word, AdminId);
|
|
false -> {error, access_denied}
|
|
end.
|
|
|
|
remove_banned_word(AdminId, Word) ->
|
|
case admin_utils:is_admin(AdminId) of
|
|
true -> core_banned_words:remove_banned_word(Word);
|
|
false -> {error, access_denied}
|
|
end.
|
|
|
|
list_banned_words(AdminId) ->
|
|
case admin_utils:is_admin(AdminId) of
|
|
true -> {ok, core_banned_words:list_banned_words()};
|
|
false -> {error, access_denied}
|
|
end.
|
|
|
|
%% ============ Контент-фильтр =============================
|
|
|
|
check_content(Text) ->
|
|
Words = core_banned_words:list_banned_words(),
|
|
LowerText = string:lowercase(binary_to_list(Text)),
|
|
lists:any(fun(W) ->
|
|
string:str(LowerText, binary_to_list(W#banned_word.word)) > 0
|
|
end, Words).
|
|
|
|
auto_moderate(Text) ->
|
|
Words = core_banned_words:list_banned_words(),
|
|
lists:foldl(fun(W, Acc) ->
|
|
WordStr = binary_to_list(W#banned_word.word),
|
|
LowerAccStr = string:lowercase(binary_to_list(Acc)),
|
|
case string:str(LowerAccStr, WordStr) of
|
|
0 -> Acc;
|
|
Pos ->
|
|
Len = length(WordStr),
|
|
Start = binary:part(Acc, {0, Pos-1}),
|
|
Rest = binary:part(Acc, {Pos-1+Len, byte_size(Acc)-Pos+1-Len}),
|
|
<<Start/binary, "***", Rest/binary>>
|
|
end
|
|
end, Text, Words).
|
|
|
|
%% ============ Заморозка/разморозка =======================
|
|
|
|
freeze_calendar(AdminId, CalendarId) ->
|
|
case admin_utils:is_admin(AdminId) of
|
|
true ->
|
|
case core_calendar:get_by_id(CalendarId) of
|
|
{ok, _Calendar} ->
|
|
core_calendar:update(CalendarId, [{status, frozen}]);
|
|
Error -> Error
|
|
end;
|
|
false -> {error, access_denied}
|
|
end.
|
|
|
|
unfreeze_calendar(AdminId, CalendarId) ->
|
|
case admin_utils:is_admin(AdminId) of
|
|
true ->
|
|
case core_calendar:get_by_id(CalendarId) of
|
|
{ok, _Calendar} ->
|
|
core_calendar:update(CalendarId, [{status, active}]);
|
|
Error -> Error
|
|
end;
|
|
false -> {error, access_denied}
|
|
end.
|
|
|
|
freeze_event(AdminId, EventId) ->
|
|
case admin_utils:is_admin(AdminId) of
|
|
true ->
|
|
case core_event:get_by_id(EventId) of
|
|
{ok, _Event} ->
|
|
core_event:update(EventId, [{status, frozen}]);
|
|
Error -> Error
|
|
end;
|
|
false -> {error, access_denied}
|
|
end.
|
|
|
|
unfreeze_event(AdminId, EventId) ->
|
|
case admin_utils:is_admin(AdminId) of
|
|
true ->
|
|
case core_event:get_by_id(EventId) of
|
|
{ok, _Event} ->
|
|
core_event:update(EventId, [{status, active}]);
|
|
Error -> Error
|
|
end;
|
|
false -> {error, access_denied}
|
|
end.
|
|
|
|
%% ============ Вспомогательные функции ====================
|
|
|
|
target_exists(event, EventId) ->
|
|
case core_event:get_by_id(EventId) of
|
|
{ok, _} -> true;
|
|
_ -> false
|
|
end;
|
|
target_exists(calendar, CalendarId) ->
|
|
case core_calendar:get_by_id(CalendarId) of
|
|
{ok, _} -> true;
|
|
_ -> false
|
|
end;
|
|
target_exists(_, _) -> false. |