168 lines
5.4 KiB
Ruby
Raw Permalink Normal View History

2024-12-12 09:17:25 +11:00
# frozen_string_literal: true
module DiscourseAi
module Admin
class AiSpamController < ::Admin::AdminController
requires_plugin "discourse-ai"
def show
render json: AiSpamSerializer.new(spam_config, root: false)
end
def update
initial_settings = AiModerationSetting.spam
initial_custom_instructions = initial_settings&.data&.dig("custom_instructions")
initial_llm_model_id = initial_settings&.llm_model_id
2024-12-12 09:17:25 +11:00
updated_params = {}
if allowed_params.key?(:llm_model_id)
llm_model_id = updated_params[:llm_model_id] = allowed_params[:llm_model_id]
if llm_model_id.to_i < 0 &&
!SiteSetting.ai_spam_detection_model_allowed_seeded_models_map.include?(
llm_model_id.to_s,
2024-12-12 09:17:25 +11:00
)
return(
render_json_error(
I18n.t("discourse_ai.llm.configuration.invalid_seeded_model"),
status: 422,
)
)
end
end
updated_params[:data] = {
custom_instructions: allowed_params[:custom_instructions],
} if allowed_params.key?(:custom_instructions)
if updated_params.present?
# not using upsert cause we will not get the correct validation errors
if AiModerationSetting.spam
AiModerationSetting.spam.update!(updated_params)
else
AiModerationSetting.create!(updated_params.merge(setting_type: :spam))
end
log_ai_spam_update(initial_llm_model_id, initial_custom_instructions, allowed_params)
2024-12-12 09:17:25 +11:00
end
is_enabled = ActiveModel::Type::Boolean.new.cast(allowed_params[:is_enabled])
if allowed_params.key?(:is_enabled)
if is_enabled && !AiModerationSetting.spam&.llm_model_id
return(
render_json_error(
I18n.t("discourse_ai.llm.configuration.must_select_model"),
status: 422,
)
)
end
SiteSetting.set_and_log("ai_spam_detection_enabled", is_enabled, current_user)
2024-12-12 09:17:25 +11:00
end
render json: AiSpamSerializer.new(spam_config, root: false)
end
def test
url = params[:post_url].to_s
post = nil
if url.match?(/^\d+$/)
post_id = url.to_i
post = Post.find_by(id: post_id)
end
route = UrlHelper.rails_route_from_url(url) if !post
if route
if route[:controller] == "topics"
post_number = route[:post_number] || 1
post = Post.with_deleted.find_by(post_number: post_number, topic_id: route[:topic_id])
end
end
raise Discourse::NotFound if !post
result =
DiscourseAi::AiModeration::SpamScanner.test_post(
post,
custom_instructions: params[:custom_instructions],
llm_id: params[:llm_id],
)
render json: result
end
def fix_errors
case params[:error]
when "spam_scanner_not_admin"
begin
DiscourseAi::AiModeration::SpamScanner.fix_spam_scanner_not_admin
render json: success_json
rescue ActiveRecord::RecordInvalid
render_json_error(
I18n.t("discourse_ai.spam_detection.bot_user_update_failed"),
status: :unprocessable_entity,
)
rescue StandardError
render_json_error(
I18n.t("discourse_ai.spam_detection.unexpected"),
status: :internal_server_error,
)
end
else
render_json_error(
I18n.t("discourse_ai.spam_detection.invalid_error_type"),
status: :bad_request,
)
end
end
2024-12-12 09:17:25 +11:00
private
def log_ai_spam_update(initial_llm_model_id, initial_custom_instructions, params)
changes_to_log = {}
if params.key?(:llm_model_id) && initial_llm_model_id.to_s != params[:llm_model_id].to_s
old_model_name =
LlmModel.find_by(id: initial_llm_model_id)&.display_name || initial_llm_model_id
new_model_name =
LlmModel.find_by(id: params[:llm_model_id])&.display_name || params[:llm_model_id]
changes_to_log[:llm_model_id] = "#{old_model_name}#{new_model_name}"
end
if params.key?(:custom_instructions) &&
initial_custom_instructions != params[:custom_instructions]
changes_to_log[:custom_instructions] = params[:custom_instructions]
end
if changes_to_log.present?
changes_to_log[:subject] = I18n.t("discourse_ai.spam_detection.logging_subject")
logger = DiscourseAi::Utils::AiStaffActionLogger.new(current_user)
logger.log_custom("update_ai_spam_settings", changes_to_log)
end
end
2024-12-12 09:17:25 +11:00
def allowed_params
params.permit(:is_enabled, :llm_model_id, :custom_instructions)
end
def spam_config
spam_config = {
enabled: SiteSetting.ai_spam_detection_enabled,
settings: AiModerationSetting.spam,
}
spam_config[:stats] = DiscourseAi::AiModeration::SpamReport.generate(min_date: 1.week.ago)
if spam_config[:stats].scanned_count > 0
spam_config[
:flagging_username
] = DiscourseAi::AiModeration::SpamScanner.flagging_user&.username
end
spam_config
end
end
end
end