Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
412 additions
and
374 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# frozen_string_literal: true | ||
|
||
module DiscourseSolved::PostSerializerExtension | ||
extend ActiveSupport::Concern | ||
|
||
private | ||
|
||
def topic | ||
topic_view&.topic || object.topic | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# frozen_string_literal: true | ||
|
||
module DiscourseSolved::TopicPostersSummaryExtension | ||
extend ActiveSupport::Concern | ||
|
||
prepended { alias old_user_ids user_ids } | ||
|
||
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Oops, something went wrong.