-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}), <> 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.