# Discourse Retort

**URL:** https://meta.discourse.org/t/discourse-retort/35903
**Category:** Plugin
**Tags:** end-of-life
**Created:** [November 22, 2015, 11:53am UTC](https://meta.discourse.org/t/discourse-retort/35903 "2015-11-22T11:53:58Z")
**Posts on this page:** 20
**Page:** 23

<div class="post-metadata">

### Author: ![wolftune](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/wolftune/32/103569_2.png) [@wolftune](https://meta.discourse.org/u/wolftune)
#### Post date: [August 3, 2022, 11:48pm UTC](https://meta.discourse.org/t/discourse-retort/35903/460 "2022-08-03T23:48:14Z")

</div>

I opened a new request [Support multiple-reactions per post (Retort style)](https://meta.discourse.org/t/support-multiple-reactions-per-post-retort-style/235064) about multiple-reactions-per-post, since the other link is only for offering more reaction choices for the one-and-only reaction that Discourse Reactions allows.

---

<div class="post-metadata">

### Author: ![JammyDodger](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/jammydodger/32/254611_2.png) [@JammyDodger](https://meta.discourse.org/u/JammyDodger)
#### Post date: [August 4, 2022, 5:34am UTC](https://meta.discourse.org/t/discourse-retort/35903/461 "2022-08-04T05:34:24Z")

</div>

> [@bsawicki](#):
>
> It just kinda sucks to retire the alternative before this is fully available.

The Retort plugin isn’t an #official one so we don’t have any say in when it stops being actively developed and maintained by the community. 🤷‍♂️ The best we can do is try and keep people informed where possible so they have some time to find an alternative (or at least give their members a heads-up to try and soften the disappointment).

Hopefully those two #Contribute > Feature requests will be adopted into the #reactions plugin at some point, but as yet they’re still in the ‘nice ideas’ stage. But I’ve got my fingers crossed. 🤞

---

<div class="post-metadata">

### Author: ![angus](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/angus/32/341715_2.png) [@angus](https://meta.discourse.org/u/angus)
#### Post date: [August 4, 2022, 6:49am UTC](https://meta.discourse.org/t/discourse-retort/35903/462 "2022-08-04T06:49:12Z")

</div>

> [@bsawicki](#):
>
> It just kinda sucks to retire the alternative before this is fully available.

> [@wolftune](#):
>
> I really wish Retort would be maintained for this reason. The better solution would be for Discourse Reactions to be updated to allow multiple reactions.

I understand where you’re coming from. The reality is that neither I or James have had the time to properly support Retort for some time. You’ll notice that the [last commit](https://github.com/gdpelican/retort/commit/a9740c2a84a1de89c66b5c5cf865e6118e535d72) on the repository is over a year ago (by me on 21 July 2021). It’s great that the plugin has continued to work this long and it is a testament to the quality of the work James put into building it.

When I say I don’t have the time, believe me, I wish I did! I feel sad every time I have to make one of these decisions (like with the [Landing Pages Plugin](https://meta.discourse.org/t/landing-pages-plugin/180967)). I didn’t build Retort, but I have invested time in it. When you decide to retire something, it’s like accepting that something you’ve created or loved, and spent many hours, days and weeks of your life with, must die. I know it was a tough decision for James to make when he felt he had to move on to other things.

By contrast, the Reactions Plugin is being maintained by [Discourse.org](http://Discourse.org), an organisation of over 60 people, on an active basis. It’s in use on a number of the servers used by [Discourse.org](http://Discourse.org)’s clients. Yes, it doesn’t have the same features as Retort yet, but I would urge you to pursue that feature development as an avenue. Perhaps you could convince someone like me, or [another member of Pavilion](https://coop.pavilion.tech/g/members), to PR a missing feature into the plugin. That would be a smart avenue to achieve your long term goals here.

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [August 4, 2022, 8:15am UTC](https://meta.discourse.org/t/discourse-retort/35903/463 "2022-08-04T08:15:45Z")

</div>

> [@wolftune](#):
>
> I really wish Retort would be maintained for this reason.

> [@bsawicki](#):
>
> It just kinda sucks to retire the alternative before this is fully available.

There is always #Marketplace if you want to pay a developer to bring it back to life in the meantime. But you may end up having to do this multiple times or agree a maintenance retainer.

---

<div class="post-metadata">

### Author: ![th21](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/th21/32/211915_2.png) [@th21](https://meta.discourse.org/u/th21)
#### Post date: [August 6, 2022, 6:29pm UTC](https://meta.discourse.org/t/discourse-retort/35903/464 "2022-08-06T18:29:10Z")

</div>

> [@th21](#):
>
> Is it possible to use [data explorer](https://meta.discourse.org/t/32566?silent=true) or console to find the most used emoji list? 🤔I was looking into `plugin_store_rows` table but found nothing helpful.

I guess the answer is No? I would like to migrate to reactions and try to find the popular ones…

---

<div class="post-metadata">

### Author: ![JammyDodger](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/jammydodger/32/254611_2.png) [@JammyDodger](https://meta.discourse.org/u/JammyDodger)
#### Post date: [August 6, 2022, 6:39pm UTC](https://meta.discourse.org/t/discourse-retort/35903/465 "2022-08-06T18:39:18Z")

</div>

I imagine it would be possible as they’ll be stored in the database somewhere. Unfortunately I don’t have this plugin installed on my test site to check the specifics. Is there a discourse-retort-retorts table or similar?

---

<div class="post-metadata">

### Author: ![mcdanlj](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mcdanlj/32/131829_2.png) [@mcdanlj](https://meta.discourse.org/u/mcdanlj)
#### Post date: [August 18, 2022, 12:04am UTC](https://meta.discourse.org/t/discourse-retort/35903/466 "2022-08-18T00:04:21Z")

</div>

Here’s how to get a `|`-separated string for the retorts you currently have in use:

```shell
# ./launcher enter app
# rails c

```

```ruby
retorts = {}
PostDetail.where(extra: 'retort').each do |p|
  retort = p.key.split('|').first
  (retorts[retort] ||= []) << p
end
retorts.length
retorts.keys.join('|')

```

That gives you:

- First the number of unique retort emoji used
- Then the retorts in a form you could paste into Reaction configuration, perhaps after trimming if it’s too long to work for the Reactions UI.

For me, I get this string:

```plaintext
tada|rage|money_with_wings|face_vomiting|crossed_fingers|grin|vulcan_salute|worried|slightly_smiling_face|dart|+1|relaxed|star_struck|upside_down_face|sweat_drops|astonished|frowning_face|champagne|heavy_plus_sign|bulb|joy|fireworks|zap|smile|fast_forward|grinning|clap|sandwich|heart_eyes|rofl|smiley|wave|ice_cream|sob|mortar_board|open_mouth|pray|grimacing|roll_eyes|arrow_right_hook|brain|wink|cry|nerd_face|slight_smile|confused|ok|thinking|it|heart|smirk|sleepy|eyes|disappointed|question|laughing|man_shrugging|drum|shushing_face|herb|man_facepalming|ear|scream|ok_hand|mantelpiece_clock|smiling_face_with_three_hearts|confetti_ball|sunglasses|nose|pirate_flag|neutral_face|sweat_smile|gift|pensive|dark_sunglasses|exclamation|call_me_hand|green_heart|face_with_monocle|blush|boom|hugs|stuck_out_tongue|zipper_mouth_face|slightly_frowning_face|face_with_raised_eyebrow|exploding_head|information_source|sailboat|fire|gun|carousel_horse|sparkles|hearts|pizza|frowning|drooling_face|-1|100|metal|partying_face|four_leaf_clover|grinning_face_with_smiling_eyes|scream_cat|person_shrugging|deciduous_tree|sunflower|see_no_evil|hear_no_evil|speak_no_evil|微笑|top|face_with_peeking_eye|face_with_hand_over_mouth|stethoscope|money_mouth_face"

```

If you’d like to copy a list of existing retorts into a post in discourse to discuss what to keep when migrating to Reactions, you might instead use this:

```ruby
":" + retorts.keys.join(': :') + ':'

```

For me, that’s currently this set:

“🎉 😡 💸 🤮 🤞 😁 🖖 😟 🙂 🎯 👍 😌 🤩 🙃 💦 😲 ☹ 🍾 ➕ 💡 😂 🎆 ⚡ 😄 ⏩ 😀 👏 🥪 😍 🤣 😃 👋 🍨 😭 🎓 😮 🙏 😬 🙄 ↪ 🧠 😉 😢 🤓 🙂 😕 🆗 🤔 🇮🇹 ❤ 😏 😪 👀 😞 ❓ 😆 🤷‍♂️ 🥁 🤫 🌿 🤦‍♂️ 👂 😱 👌 🕰 🥰 🎊 🕶 👃 🏴‍☠️ 😐 😅 🎁 😔 🕶 ❗ 🤙 💚 🧐 😊 💥 🤗 😛 🤐 🙁 🤨 🤯 ℹ ⛵ 🔥 🔫 🎠 ✨ ♥ 🍕 ☹ 🤤 👎 💯 🤘 🥳 🍀 😄 🙀 🤷 🌳 🌻 🙈 🙉 🙊 :微笑: 🔝 🫣 🤭 🩺 🤑”

To get a bullet list of emojis with the number of instances of each:

```ruby
retorts.keys.sort.each do |k|
  puts "* :#{k}: #{retorts[k].length}"
end

```

I won’t paste the whole bullet list of emoji, but it starts like this:

- 👍 161
- 👎 1
- 💯 1
- ↪ 1
- 😲 9
- 😊 2
- 💥 2
- 🧠 23
- 💡 3

If you want to see every post that exists for each emoji:

```ruby
retorts.keys.sort.each do |k|
  puts "* :#{k}: #{retorts[k].length}"
  retorts[k].each do |r|
    p = Post.find_by(id: r.post_id)
    next if p.nil?
    puts " * #{p.full_url}"
  end
end

```

That’s way too long to paste here!

What I don’t know is how to _migrate_ all — or some of — those retorts to reactions. There is no mention of retort in the reactions plugin so it doesn’t do it automatically. I have 927 reactions with 116 unique emoji that I’d like to migrate to reactions.

I expect that I’ll be faced with dealing this at some point, preferably before Retort just quits working; if I implement the migration I’ll plan to document it here. But at least knowing what you have might help you.

---

<div class="post-metadata">

### Author: ![mcdanlj](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mcdanlj/32/131829_2.png) [@mcdanlj](https://meta.discourse.org/u/mcdanlj)
#### Post date: [October 27, 2022, 1:34am UTC](https://meta.discourse.org/t/discourse-retort/35903/467 "2022-10-27T01:34:20Z")

</div>

In writing some experimental code to migrate Retort to Reactions, I have discovered that Retorts aren’t updated when usernames are changed.

I think that this will not be true with Reactions because `PostActions` joins to actual user records, rather than recording user names in a JSON blob in `PostDetail`.

In general, if someone decided that they wanted to adopt and maintain Retort, they should consider migrating from `PostDetail` to `PostActions` following how Reactions was done.

Similarly, it does not recognize when posts are deleted.

---

<div class="post-metadata">

### Author: ![mcdanlj](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mcdanlj/32/131829_2.png) [@mcdanlj](https://meta.discourse.org/u/mcdanlj)
#### Post date: [October 27, 2022, 4:07am UTC](https://meta.discourse.org/t/discourse-retort/35903/468 "2022-10-27T04:07:41Z")

</div>

My [Script framework to rearrange topics and categories](https://meta.discourse.org/t/script-framework-to-rearrange-topics-and-categories/241964) has grown a new function that goes a little beyond rearranging topics and categories!

I usually remember to warn folks that I don’t know ruby or ruby on rails, so my code is idiosyncratic rather than idiomatic. But it seems to work so far in my testing!

```ruby
  def migrateRetortToReactions(allowed:, likes: nil, emojimap: nil)
    # migrate where possible without overriding any existing likes
    # this is a necessarily lossy conversion, and is consistent only by ordering of PostDetail
    # no attempt is made to prefer one PostDetail record over another
    emojimap = {} if emojimap.nil?
    allowed.each do |a|
      emojimap[a] = a
    end
    retort = "retort".freeze
    emojiType = "emoji".freeze
    usermap = Hash.new { |hash, username| hash[username] = User.find_by_username(username) }
    postmap = Hash.new { |hash, post_id| hash[post_id] = Post.find(post_id) }
    likeType = PostActionType.where(name_key: "like").pluck(:id).first

    PostDetail.where(extra: retort).each do |pd|
      begin
        p = postmap[pd.post_id]
      rescue
        # PostDetail not consistent WRT delete
        $stderr.puts sprintf("Could not find post for %d: %s / %s", pd.post_id, pd.key, pd.value)
        next
      end
      emoji = pd.key.split('|').first
      users = JSON.parse(pd.value)
      users.each do |user|
        u = usermap[user]
        next if u.nil? # changed user name or deleted user leaves orphaned Retorts
        if likes.include?(emoji)
          pa = PostAction.where(post_id: p.id, user_id: u.id, post_action_type_id: likeType).first
          next unless pa.nil?
          $stderr.puts sprintf("Adding like for Retort %s for user %s in %s", emoji, user, p.url)
          PostActionCreator.create(u, p, :like, created_at: pd.created_at, silent: true)
        elsif emojimap.has_key?(emoji)
          e = emojimap[emoji]
          r = DiscourseReactions::Reaction.where(post_id: p.id, reaction_type: emojiType, reaction_value: e).first_or_create
          ru = DiscourseReactions::ReactionUser.where(user_id: u.id, post_id: p.id).first
          next unless ru.nil?
          $stderr.puts sprintf("Converting Retort %s to Reaction %s for user %s in %s", emoji, e, user, p.url)
          DiscourseReactions::ReactionUser.create(reaction_id: r.id, user_id: u.id, post_id: p.id, created_at: pd.created_at)
        else
          $stderr.puts sprintf("Ignoring unmapped Retort %s for user %s in %s", emoji, user, p.url)
        end
      end
    end
  end

```

I use the framework I built to provide a yaml configuration that looks like this:

```yaml
- migrateRetortToReactions:
    allowed:
      - rofl
      - astonished
      - crossed_fingers
      - sob
      - thinking
      - grimacing
      - frowning_face
      - drum
    likes:
      - dart
      - +1
      - joy
      - "100"
      - brain
      - heart
      - heart_eyes
      - hearts
    emojimap:
      rage: sob
      four_leaf_clover: crossed_fingers
      cry: sob
      open_mouth: astonished
      scream: frowning_face

```

However, you could just wrap that up in a ruby script including making those arguments literal ruby code, drop it in the script/ directory, and run it.

---

<div class="post-metadata">

### Author: ![angus](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/angus/32/341715_2.png) [@angus](https://meta.discourse.org/u/angus)
#### Post date: [October 27, 2022, 12:16pm UTC](https://meta.discourse.org/t/discourse-retort/35903/469 "2022-10-27T12:16:30Z")

</div>

Hey guys, as discussed in the topic above I’ve already written a migration feature of Retort to Reactions, including an admin UI.

> [@Discourse Retort](https://meta.discourse.org/t/retort-a-reaction-style-plugin-for-discourse/35903/435):
>
> I’ve written a migration script and created an admin UI to migrate retorts to reactions. It’s on this [branch](https://github.com/gdpelican/retort/tree/add_migration_to_discourse_reactions). The UI looks like this I need some advice to finish it off. It’s possible that a user could have both liked and “retorted” on a post. In the migration, I’m going to preference retorts over likes in this scenario. However the ReactionManager.toggle! access protections do not allow this. Would it be possible to add a “force” option for migrations…

For it to be production ready the maintainers of Reactions will need to make a slight change to improve the abstraction of the code in the Reactions plugin.

> [@Discourse Retort](https://meta.discourse.org/t/retort-a-reaction-style-plugin-for-discourse/35903/443):
>
> Yup, I could do that. It would be a bit of a hack though wink I’m not sure I could assume that workaround would remain viable over time. It’s also a bit risky. For example, if I just run that code the user’s post\_undo\_action\_window\_mins site setting would remained changed. You could change it back at the end of the migration, but doing setting changes like this on the fly to get around a guardian is not ideal. Ideally what I’m after here is a slight change to the ReactionManager interface to…

Supporting a production level migration between two plugins like this requires significant quality assurance otherwise issues like this can easily occur.

> [@Plugin causing errors during rebuild](https://meta.discourse.org/t/plugin-causing-errors-during-rebuild/241110/28):
>
> What is happening here is this Some people have a very old version of the question answer plugin with my personal github username in the repository URL in their app.yml file. I transferred the QnA plugin to paviliondev years ago. Github redirects repository URLs when they’re transferred, so the old urls with my personal username in it kept working. More years later Pavilion transferred the Question Answer Plugin to Discourse. Discourse initially kept the name discourse-question-answer. …

---

<div class="post-metadata">

### Author: ![mcdanlj](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mcdanlj/32/131829_2.png) [@mcdanlj](https://meta.discourse.org/u/mcdanlj)
#### Post date: [October 27, 2022, 1:18pm UTC](https://meta.discourse.org/t/discourse-retort/35903/471 "2022-10-27T13:18:39Z")

</div>

I’m sorry! I had missed those post and had merely looked in the main branch. It’s a long thread…

> [@angus](#):
>
> For it to be production ready the maintainers of Reactions will need to make a slight change to improve the abstraction of the code in the Reactions plugin.

I agree. I completely side-stepped it. It’s more than just ReactionManager.toggle! though — it really needs to pass through `created_at` doesn’t it?

The move to Reactions really changes the semantics of “like” because you can’t take it back when someone edits their post. I would not have made the same implementation choice. ☹

In any case, what I want to do is drive this from a script, and I have no interest whatsoever in driving it from a UI. I’m not the target audience for the UI, so maybe my hack being available doesn’t hurt.

---

<div class="post-metadata">

### Author: ![angus](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/angus/32/341715_2.png) [@angus](https://meta.discourse.org/u/angus)
#### Post date: [October 27, 2022, 1:46pm UTC](https://meta.discourse.org/t/discourse-retort/35903/472 "2022-10-27T13:46:23Z")

</div>

By all means, I didn’t mean to discourage you writing it for your own purposes, but I wouldn’t advise other sites to use it unless they’re familiar with the code and the data structure.

The bottom line is that the Reactions Plugin isn’t currently written in a way conducive to a stable migration that will work reliably across environments.

If anyone wishes to migrate from Retort to Reactions, [Pavilion](https://pavilion.tech) is handling these manually on a contract basis (email contact@pavilion.tech or PM me). If the Reactions Plugin is updated to allow for generalized migrations we’ll [complete the migration work](https://github.com/gdpelican/retort/compare/master...add_migration_to_discourse_reactions) to make this freely available.

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [October 28, 2022, 2:15pm UTC](https://meta.discourse.org/t/discourse-retort/35903/473 "2022-10-28T14:15:31Z")

</div>

Aha. This answers some questions I’ve had. It’s hard to make sense of 450 posts over 7 years.

> [@angus](#):
>
> The bottom line is that the Reactions Plugin isn’t currently written in a way conducive to a stable migration that will work reliably across environments.

So do I understand that what “needs” to happen (anyone is welcome to supply their own definition of “needs”) is to somehow extend Reactions so that it can more cleanly handle migrating data to it and also providing _features_ that it is missing?

How big a job is that in some wild guess of hours or dollars?

---

<div class="post-metadata">

### Author: ![angus](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/angus/32/341715_2.png) [@angus](https://meta.discourse.org/u/angus)
#### Post date: [October 28, 2022, 3:21pm UTC](https://meta.discourse.org/t/discourse-retort/35903/474 "2022-10-28T15:21:54Z")

</div>

This is broadly still accurate.

> [@angus](#):
>
> Ideally what I’m after here is a slight change to the `ReactionManager` interface to make it possible to reliably migrate retorts to reactions. Currently it’s only set up to handle requests from the client.
> 
> One way to do that would be to
> 
> - abstract the guardian in `toggle!` to an `ensure_can_toggle` method
> - make the `ensure_can_toggle` method subject to a `force` option
> 
> This is the approach typically taken to handle migrations or backend imports in other parts of Discourse (if you do a search in `app/` or `lib/` for `force` you’ll see a few examples).

> [@pfaffman](#):
>
> How big a job is that in some wild guess of hours or dollars?

![](https://global.discourse-cdn.com/meta/original/4X/4/7/e/47ec5002c19e72265752f660d71cd9a26089be59.gif)  
If the opportunity for a PR is realistically there I’d probably just do it for a good bottle of red. It is Friday night after all.

But, being slightly more serious, what we’re talking about here is a minor refactor of the Reactions plugin `ReactionManager`. That kind of work is typically not accepted via PR. There would need to be buy-in from the maintainers of Reactions.

---

<div class="post-metadata">

### Author: ![mcdanlj](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mcdanlj/32/131829_2.png) [@mcdanlj](https://meta.discourse.org/u/mcdanlj)
#### Post date: [October 29, 2022, 2:17am UTC](https://meta.discourse.org/t/discourse-retort/35903/475 "2022-10-29T02:17:26Z")

</div>

I think you also would want to make sure the likes are `silent` and `created_at` is handled for likes and reactions; otherwise users are spammed with notifications from the migration. (I saw this in my test site for my own login.)

For some reason, even with `created_by` handled, I still trigger the `out of love` max likes, and I didn’t investigate further, because I got rid of all the other notifications.

@joffreyjaffeux any reason not to expose the necessary functionality for a clean migration?

---

<div class="post-metadata">

### Author: ![schungx](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/schungx/32/70989_2.png) [@schungx](https://meta.discourse.org/u/schungx)
#### Post date: [November 20, 2022, 10:44am UTC](https://meta.discourse.org/t/discourse-retort/35903/476 "2022-11-20T10:44:55Z")

</div>

I have just moved to Reactions (because I guess it is official and all… ) but would hate to lose all previous retort data.

---

<div class="post-metadata">

### Author: ![angus](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/angus/32/341715_2.png) [@angus](https://meta.discourse.org/u/angus)
#### Post date: [November 21, 2022, 9:40am UTC](https://meta.discourse.org/t/discourse-retort/35903/477 "2022-11-21T09:40:09Z")

</div>

I’m sorry, but providing a stable migration is not possible at the moment for the reasons mentioned above.

---

<div class="post-metadata">

### Author: ![Boost](https://avatars.discourse-cdn.com/v4/letter/b/8e8cbc/32.png) [@Boost](https://meta.discourse.org/u/Boost)
#### Post date: [January 27, 2023, 9:16am UTC](https://meta.discourse.org/t/discourse-retort/35903/478 "2023-01-27T09:16:11Z")

</div>

Well, it now happened, I could not update discourse because of the retort plugin.

This is the database migration error I got:

```plaintext
could not create unique index "index_post_details_on_post_id_and_key_ccnew_ccnew" DETAIL: Key (post_id, key)=(30297, +1|retort) is duplicated.

```

I used this script as a base for my own migration code. Here’s what I did.

- To get discourse working again, I had to override the “version” in the template .yml file to a commit from about two weeks ago in discourse repo
- Rebuild with the reactions plugin added to get the site back up
- I configured the reactions plugin with the same set of reactions as retort. I do not use any reaction that could be interpreted as like
- I used @mcdanlj’s script a bit modified with the following steps (as I wanted to migrate all retorts and I had 1-to-1 mapping between retorts and reactions already):
- Run `./launcher enter app`
- Run `rails c`
- Paste in the following (it seems that rails console will echo back the code with incorrect line changes, I added double line changes but that didn’t really change the output, but if someone gets a syntax error with the following code, add an extra line after each line):

```ruby
def migrateRetortToReactions()
  retort = "retort".freeze
  emojiType = "emoji".freeze
  usermap = Hash.new { |hash, username| hash[username] = User.find_by_username(username) }
  postmap = Hash.new { |hash, post_id| hash[post_id] = Post.find(post_id) }
  likeType = PostActionType.where(name_key: "like").pluck(:id).first
  PostDetail.where(extra: retort).each do |pd|
    begin
      p = postmap[pd.post_id]
    rescue
      # PostDetail not consistent WRT delete
      $stderr.puts sprintf("Could not find post for %d: %s / %s", pd.post_id, pd.key, pd.value)
      next
    end

    emoji = pd.key.split('|').first
    users = JSON.parse(pd.value)
    users.each do |user|
      u = usermap[user]
      next if u.nil? # changed user name or deleted user leaves orphaned Retorts
      e = emoji
      r = DiscourseReactions::Reaction.where(post_id: p.id, reaction_type: emojiType, reaction_value: e).first_or_create
      ru = DiscourseReactions::ReactionUser.where(user_id: u.id, post_id: p.id).first
      next unless ru.nil?
      $stderr.puts sprintf("Converting Retort %s to Reaction %s for user %s in %s", emoji, e, user, p.url)
      DiscourseReactions::ReactionUser.create(reaction_id: r.id, user_id: u.id, post_id: p.id, created_at: pd.created_at)
    end
  end
end

```

- At this point I made a site backup just in case
- Then run `migrateRetortToReactions` which should take a while. For me I didn’t see or run into any issues. After running the console seems to show all the changed objects so hit `q` to exit
- Now on the site it should be the case that the data is migrated correctly
- As a final step you need to run: `PostDetail.where(extra: "retort").destroy_all` which will delete the retort data
- Now I was able to then rebuild my site with latest discourse version and without the retort plugin

So all in all, not _that_ difficult to migrate but it was pretty scary, and as discussed before this overwrites likes with reactions on posts that had both likes and retorts by the same user.

---

<div class="post-metadata">

### Author: ![Hifihedgehog](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/hifihedgehog/32/140207_2.png) [@Hifihedgehog](https://meta.discourse.org/u/Hifihedgehog)
#### Post date: [October 10, 2023, 5:42pm UTC](https://meta.discourse.org/t/discourse-retort/35903/479 "2023-10-10T17:42:58Z")

</div>

Agreed! Multiple reactions and being able to pick from all reactions is a must for my community. People have come to expect it from the Discord chat server world so reverting that feature in my community is a no-go. Fortunately, this plugin has not broken yet for me, but I am consigned to the reality that I am slowly counting down the days. I hope the desired solution comes either from the third-party community or Discourse officially in the next six months. Otherwise, I would be forced to hold my forum at an older build version indefinitely if it ends up being that this plugin breaks updates down the line.

> [@Add ... option to Discourse Reactions](https://meta.discourse.org/t/add-option-to-discourse-reactions/227785/19):
>
> We would love to build it, but sadly do not have bandwidth, unless somehow sponsored by an enterprise customer I don’t see this happening for another 6 or so months. I am partially open to contracting out this work, but it is highly complicated, the concern here is that we would end up spending the same amount of time of building it as we would reviewing a 3rd party sponsored contribution.

---

<div class="post-metadata">

### Author: ![Hifihedgehog](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/hifihedgehog/32/140207_2.png) [@Hifihedgehog](https://meta.discourse.org/u/Hifihedgehog)
#### Post date: [January 13, 2024, 6:00pm UTC](https://meta.discourse.org/t/discourse-retort/35903/480 "2024-01-13T18:00:59Z")

</div>

With the new Ember 5 changes, Retort is now dead. Exploring options to preserve its functionality.

> [@Rebuilding a fresh Discourse install pre-Ember 5 (targeting the beta channel), I am presented with an endless loading screen](https://meta.discourse.org/t/rebuilding-a-fresh-discourse-install-pre-ember-5-targeting-the-beta-channel-i-am-presented-with-an-endless-loading-screen/291530/8):
>
> Verdict: For those like me hanging on to it, with Ember 5, Retort is now dead. frowning Looking into options to preserve its features.

[Previous page](https://meta.discourse.org/t/discourse-retort/35903.md?page=22)

[Next page](https://meta.discourse.org/t/discourse-retort/35903.md?page=24)
