From 1cdd3fd708a48a36af60d4f1c9bb8178df0f384d Mon Sep 17 00:00:00 2001 From: Martin Brennan Date: Wed, 19 Nov 2025 09:36:08 +1000 Subject: [PATCH] FIX: Various bugs from 2024 rewind (#29) * Use post excerpt for best posts to avoid giant posts ruining it * Make sure short emojis (e.g. `:joy:`) render in best posts and best topics * Make images show in best post excerpts (requires core change) * Fix invite action error, using column that doesn't exist * Add missing # for top category slugs * Refactor report service + controller a little to make it easier to figure out what went wrong if it fails, and to use the guardian user Copies a couple of fixes from https://github.com/discourse/discourse-rewind/pull/28 to make things work locally, the conflicts will be easy to resolve. **Best topics before** image **Best topics after** image **Categories before** image **Categories after** image --- .../discourse_rewind/rewinds_controller.rb | 8 ++++++-- .../discourse_rewind/action/best_posts.rb | 14 ++++++++++++-- app/services/discourse_rewind/fetch_reports.rb | 10 +++------- .../discourse/components/reports/best-posts.gjs | 11 ++++++----- .../discourse/components/reports/best-topics.gjs | 5 +++-- .../reports/most-viewed-categories.gjs | 2 +- config/locales/server.en.yml | 3 +++ spec/requests/rewinds_controller_spec.rb | 16 ++++++++++++++++ 8 files changed, 50 insertions(+), 19 deletions(-) diff --git a/app/controllers/discourse_rewind/rewinds_controller.rb b/app/controllers/discourse_rewind/rewinds_controller.rb index fb7871e..b71d2ff 100644 --- a/app/controllers/discourse_rewind/rewinds_controller.rb +++ b/app/controllers/discourse_rewind/rewinds_controller.rb @@ -8,8 +8,12 @@ module ::DiscourseRewind def show DiscourseRewind::FetchReports.call(service_params) do - on_model_not_found(:year) { raise Discourse::NotFound } - on_model_not_found(:user) { raise Discourse::NotFound } + on_model_not_found(:year) do + raise Discourse::NotFound.new(nil, custom_message: "discourse_rewind.invalid_year") + end + on_model_not_found(:reports) do + raise Discourse::NotFound.new(nil, custom_message: "discourse_rewind.report_failed") + end on_success { |reports:| render json: MultiJson.dump(reports), status: :ok } end end diff --git a/app/services/discourse_rewind/action/best_posts.rb b/app/services/discourse_rewind/action/best_posts.rb index b3c3783..547d9db 100644 --- a/app/services/discourse_rewind/action/best_posts.rb +++ b/app/services/discourse_rewind/action/best_posts.rb @@ -10,9 +10,19 @@ module DiscourseRewind .where(created_at: date) .where(deleted_at: nil) .where("post_number > 1") - .order("like_count DESC NULLS LAST") + .order("like_count DESC NULLS LAST, created_at ASC") .limit(3) - .pluck(:post_number, :topic_id, :like_count, :reply_count, :raw, :cooked) + .select(:post_number, :topic_id, :like_count, :reply_count, :raw, :cooked) + .map do |post| + { + post_number: post.post_number, + topic_id: post.topic_id, + like_count: post.like_count, + reply_count: post.reply_count, + excerpt: + post.excerpt(200, { strip_links: true, remap_emoji: true, keep_images: true }), + } + end { data: best_posts, identifier: "best-posts" } end diff --git a/app/services/discourse_rewind/fetch_reports.rb b/app/services/discourse_rewind/fetch_reports.rb index 79f0049..679b916 100644 --- a/app/services/discourse_rewind/fetch_reports.rb +++ b/app/services/discourse_rewind/fetch_reports.rb @@ -41,16 +41,11 @@ module DiscourseRewind ] model :year - model :user model :date model :reports private - def fetch_user(guardian:) - User.find_by_username(guardian.user.username) - end - def fetch_year current_date = Time.zone.now current_month = current_date.month @@ -76,12 +71,13 @@ module DiscourseRewind Date.new(year).all_year end - def fetch_reports(date:, user:, guardian:, year:) + def fetch_reports(date:, guardian:, year:) key = "rewind:#{guardian.user.username}:#{year}" reports = Discourse.redis.get(key) if !reports - reports = REPORTS.map { |report| report.call(date:, user:, guardian:) }.compact + reports = + REPORTS.map { |report| report.call(date:, user: guardian.user, guardian:) }.compact Discourse.redis.setex(key, CACHE_DURATION, MultiJson.dump(reports)) else reports = MultiJson.load(reports, symbolize_keys: true) diff --git a/assets/javascripts/discourse/components/reports/best-posts.gjs b/assets/javascripts/discourse/components/reports/best-posts.gjs index 2ba8c8b..a72b5ca 100644 --- a/assets/javascripts/discourse/components/reports/best-posts.gjs +++ b/assets/javascripts/discourse/components/reports/best-posts.gjs @@ -1,6 +1,5 @@ import Component from "@glimmer/component"; import { concat } from "@ember/helper"; -import { get } from "@ember/object"; import { htmlSafe } from "@ember/template"; import icon from "discourse/helpers/d-icon"; import { i18n } from "discourse-i18n"; @@ -22,13 +21,15 @@ export default class BestPosts extends Component {
-
{{htmlSafe (get post "5")}}
+

{{htmlSafe + post.excerpt + }}

diff --git a/assets/javascripts/discourse/components/reports/best-topics.gjs b/assets/javascripts/discourse/components/reports/best-topics.gjs index a0ab586..19c8de1 100644 --- a/assets/javascripts/discourse/components/reports/best-topics.gjs +++ b/assets/javascripts/discourse/components/reports/best-topics.gjs @@ -1,6 +1,7 @@ import Component from "@glimmer/component"; import { concat } from "@ember/helper"; import { htmlSafe } from "@ember/template"; +import replaceEmoji from "discourse/helpers/replace-emoji"; import { i18n } from "discourse-i18n"; export default class BestTopics extends Component { @@ -25,8 +26,8 @@ export default class BestTopics extends Component {

{{topic.title}}

- {{htmlSafe - topic.excerpt + {{replaceEmoji + (htmlSafe topic.excerpt) }} {{/each}} diff --git a/assets/javascripts/discourse/components/reports/most-viewed-categories.gjs b/assets/javascripts/discourse/components/reports/most-viewed-categories.gjs index 15c2be7..0361b71 100644 --- a/assets/javascripts/discourse/components/reports/most-viewed-categories.gjs +++ b/assets/javascripts/discourse/components/reports/most-viewed-categories.gjs @@ -13,7 +13,7 @@ const MostViewedCategories =