Skip to content

Commit

Permalink
DEV: Fix new Rubocop offenses
Browse files Browse the repository at this point in the history
  • Loading branch information
Flink committed Mar 6, 2024
1 parent b50b118 commit 4c6ddcf
Show file tree
Hide file tree
Showing 13 changed files with 417 additions and 382 deletions.
36 changes: 30 additions & 6 deletions Gemfile.lock
@@ -1,19 +1,38 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (7.1.3.2)
base64
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
minitest (>= 5.1)
mutex_m
tzinfo (~> 2.0)
ast (2.4.2)
base64 (0.2.0)
bigdecimal (3.1.6)
concurrent-ruby (1.2.3)
connection_pool (2.4.1)
drb (2.2.1)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
json (2.7.1)
language_server-protocol (3.17.0.3)
minitest (5.22.2)
mutex_m (0.2.0)
parallel (1.24.0)
parser (3.3.0.4)
parser (3.3.0.5)
ast (~> 2.4.1)
racc
prettier_print (1.2.1)
racc (1.7.3)
rainbow (3.1.1)
regexp_parser (2.9.0)
rexml (3.2.6)
rubocop (1.60.0)
rubocop (1.61.0)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
Expand All @@ -24,22 +43,27 @@ GEM
rubocop-ast (>= 1.30.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.30.0)
parser (>= 3.2.1.0)
rubocop-ast (1.31.1)
parser (>= 3.3.0.4)
rubocop-capybara (2.20.0)
rubocop (~> 1.41)
rubocop-discourse (3.6.0)
rubocop-discourse (3.7.1)
activesupport (>= 6.1)
rubocop (>= 1.59.0)
rubocop-capybara (>= 2.0.0)
rubocop-factory_bot (>= 2.0.0)
rubocop-rspec (>= 2.25.0)
rubocop-factory_bot (2.25.1)
rubocop (~> 1.41)
rubocop-rspec (2.26.1)
rubocop-rspec (2.27.1)
rubocop (~> 1.40)
rubocop-capybara (~> 2.17)
rubocop-factory_bot (~> 2.22)
ruby-progressbar (1.13.0)
syntax_tree (6.2.0)
prettier_print (>= 1.2.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (2.5.0)

PLATFORMS
Expand Down
41 changes: 41 additions & 0 deletions app/controllers/answer_controller.rb
@@ -0,0 +1,41 @@
# frozen_string_literal: true

class DiscourseSolved::AnswerController < ::ApplicationController
requires_plugin DiscourseSolved::PLUGIN_NAME

def accept
limit_accepts

post = Post.find(params[:id].to_i)

topic = post.topic
topic ||= Topic.with_deleted.find(post.topic_id) if guardian.is_staff?

guardian.ensure_can_accept_answer!(topic, post)

DiscourseSolved.accept_answer!(post, current_user, topic: topic)

render json: success_json
end

def unaccept
limit_accepts

post = Post.find(params[:id].to_i)

topic = post.topic
topic ||= Topic.with_deleted.find(post.topic_id) if guardian.is_staff?

guardian.ensure_can_accept_answer!(topic, post)

DiscourseSolved.unaccept_answer!(post, topic: topic)

render json: success_json
end

def limit_accepts
return if current_user.staff?
RateLimiter.new(nil, "accept-hr-#{current_user.id}", 20, 1.hour).performed!
RateLimiter.new(nil, "accept-min-#{current_user.id}", 4, 30.seconds).performed!
end
end
85 changes: 85 additions & 0 deletions app/lib/before_head_close.rb
@@ -0,0 +1,85 @@
# frozen_string_literal: true

class DiscourseSolved::BeforeHeadClose
attr_reader :controller

def initialize(controller)
@controller = controller
end

def html
return "" if !controller.instance_of? TopicsController

topic_view = controller.instance_variable_get(:@topic_view)
topic = topic_view&.topic
return "" if !topic
# note, we have canonicals so we only do this for page 1 at the moment
# it can get confusing to have this on every page and it should make page 1
# a bit more prominent + cut down on pointless work

return "" if SiteSetting.solved_add_schema_markup == "never"

allowed =
controller.guardian.allow_accepted_answers?(topic.category_id, topic.tags.pluck(:name))
return "" if !allowed

first_post = topic_view.posts&.first
return "" if first_post&.post_number != 1

question_json = {
"@type" => "Question",
"name" => topic.title,
"text" => get_schema_text(first_post),
"upvoteCount" => first_post.like_count,
"answerCount" => 0,
"datePublished" => topic.created_at,
"author" => {
"@type" => "Person",
"name" => topic.user&.username,
"url" => topic.user&.full_url,
},
}

if accepted_answer =
Post.find_by(
id: topic.custom_fields[::DiscourseSolved::ACCEPTED_ANSWER_POST_ID_CUSTOM_FIELD],
)
question_json["answerCount"] = 1
question_json[:acceptedAnswer] = {
"@type" => "Answer",
"text" => get_schema_text(accepted_answer),
"upvoteCount" => accepted_answer.like_count,
"datePublished" => accepted_answer.created_at,
"url" => accepted_answer.full_url,
"author" => {
"@type" => "Person",
"name" => accepted_answer.user&.username,
"url" => accepted_answer.user&.full_url,
},
}
else
return "" if SiteSetting.solved_add_schema_markup == "answered only"
end

[
'<script type="application/ld+json">',
MultiJson
.dump(
"@context" => "http://schema.org",
"@type" => "QAPage",
"name" => topic&.title,
"mainEntity" => question_json,
)
.gsub("</", "<\\/")
.html_safe,
"</script>",
].join("")
end

private

def get_schema_text(post)
post.excerpt(nil, keep_onebox_body: true).presence ||
post.excerpt(nil, keep_onebox_body: true, keep_quotes: true)
end
end
13 changes: 13 additions & 0 deletions app/lib/category_extension.rb
@@ -0,0 +1,13 @@
# frozen_string_literal: true

module DiscourseSolved::CategoryExtension
extend ActiveSupport::Concern

prepended { after_save :reset_accepted_cache, if: -> { SiteSetting.solved_enabled? } }

private

def reset_accepted_cache
::DiscourseSolved::AcceptedAnswerCache.reset_accepted_answer_cache
end
end
11 changes: 11 additions & 0 deletions app/lib/post_serializer_extension.rb
@@ -0,0 +1,11 @@
# frozen_string_literal: true

module DiscourseSolved::PostSerializerExtension
extend ActiveSupport::Concern

private

def topic
topic_view&.topic || object.topic
end
end
30 changes: 30 additions & 0 deletions app/lib/topic_posters_summary_extension.rb
@@ -0,0 +1,30 @@
# frozen_string_literal: true

module DiscourseSolved::TopicPostersSummaryExtension
extend ActiveSupport::Concern

def descriptions_by_id
if !defined?(@descriptions_by_id)
super(ids: old_user_ids)

if id = topic.accepted_answer_user_id
@descriptions_by_id[id] ||= []
@descriptions_by_id[id] << I18n.t(:accepted_answer)
end
end

super
end

def last_poster_is_topic_creator?
super || topic.accepted_answer_user_id == topic.last_post_user_id
end

def user_ids
if id = topic.accepted_answer_user_id
super.insert(1, id)
else
super
end
end
end
54 changes: 54 additions & 0 deletions app/lib/topic_view_serializer_extension.rb
@@ -0,0 +1,54 @@
# frozen_string_literal: true

module DiscourseSolved::TopicViewSerializerExtension
extend ActiveSupport::Concern

prepended { attributes :accepted_answer }

def include_accepted_answer?
SiteSetting.solved_enabled? && accepted_answer_post_id
end

def accepted_answer
if info = accepted_answer_post_info
{ post_number: info[0], username: info[1], excerpt: info[2], name: info[3] }
end
end

private

def accepted_answer_post_info
post_info =
if post = object.posts.find { |p| p.post_number == accepted_answer_post_id }
[post.post_number, post.user.username, post.cooked, post.user.name]
else
Post
.where(id: accepted_answer_post_id, topic_id: object.topic.id)
.joins(:user)
.pluck("post_number", "username", "cooked", "name")
.first
end

if post_info
post_info[2] = if SiteSetting.solved_quote_length > 0
PrettyText.excerpt(post_info[2], SiteSetting.solved_quote_length, keep_emoji_images: true)
else
nil
end

post_info[3] = nil if !SiteSetting.enable_names || !SiteSetting.display_name_on_posts

post_info
end
end

def accepted_answer_post_id
id = object.topic.custom_fields[::DiscourseSolved::ACCEPTED_ANSWER_POST_ID_CUSTOM_FIELD]
# a bit messy but race conditions can give us an array here, avoid
begin
id && id.to_i
rescue StandardError
nil
end
end
end
9 changes: 9 additions & 0 deletions app/lib/user_summary_extension.rb
@@ -0,0 +1,9 @@
# frozen_string_literal: true

module DiscourseSolved::UserSummaryExtension
extend ActiveSupport::Concern

def solved_count
UserAction.where(user: @user).where(action_type: UserAction::SOLVED).count
end
end
22 changes: 22 additions & 0 deletions app/lib/web_hook_extension.rb
@@ -0,0 +1,22 @@
# frozen_string_literal: true

module DiscourseSolved::WebHookExtension
extend ActiveSupport::Concern

class_methods do
def enqueue_solved_hooks(event, post, payload = nil)
if active_web_hooks(event).exists? && post.present?
payload ||= WebHook.generate_payload(:post, post)

WebHook.enqueue_hooks(
:solved,
event,
id: post.id,
category_id: post.topic&.category_id,
tag_ids: post.topic&.tags&.pluck(:id),
payload: payload,
)
end
end
end
end

0 comments on commit 4c6ddcf

Please sign in to comment.