J’ai ouvert une nouvelle requête Support multiple-reactions per post (Retort style) concernant les réactions multiples par publication, car l’autre lien ne sert qu’à offrir plus de choix de réactions pour la seule réaction que Discourse Reactions autorise.
Le plugin Retort n’est pas un plugin #officiel, nous n’avons donc aucun contrôle sur le moment où il cesse d’être activement développé et maintenu par la communauté.
Tout ce que nous pouvons faire, c’est essayer d’informer les gens dans la mesure du possible afin qu’ils aient le temps de trouver une alternative (ou du moins d’en informer leurs membres pour tenter d’atténuer la déception).
Espérons que ces deux demandes de #fonctionnalité seront adoptées dans le plugin #réactions à un moment donné, mais pour l’instant, elles en sont encore au stade de ‘bonnes idées’. Mais j’ai les doigts croisés. ![]()
Je comprends votre point de vue. La réalité est que ni James ni moi n’avons eu le temps de supporter correctement Retort depuis un certain temps. Vous remarquerez que le dernier commit sur le dépôt date de plus d’un an (par moi, le 21 juillet 2021). C’est formidable que le plugin ait continué à fonctionner aussi longtemps et c’est un témoignage de la qualité du travail que James a investi dans sa création.
Quand je dis que je n’ai pas le temps, croyez-moi, j’aimerais l’avoir ! Je me sens triste chaque fois que je dois prendre une de ces décisions (comme avec le Landing Pages Plugin). Je n’ai pas créé Retort, mais j’y ai investi du temps. Quand on décide de retirer quelque chose, c’est comme accepter que quelque chose que l’on a créé ou aimé, et avec lequel on a passé de nombreuses heures, jours et semaines de sa vie, doit mourir. Je sais que ce fut une décision difficile pour James quand il a senti qu’il devait passer à autre chose.
En revanche, le Reactions Plugin est maintenu par Discourse.org, une organisation de plus de 60 personnes, de manière active. Il est utilisé sur un certain nombre de serveurs utilisés par les clients de Discourse.org. Oui, il n’a pas encore les mêmes fonctionnalités que Retort, mais je vous encourage à poursuivre le développement de ces fonctionnalités comme une voie à suivre. Peut-être pourriez-vous convaincre quelqu’un comme moi, ou un autre membre de Pavilion, de faire une PR pour ajouter une fonctionnalité manquante au plugin. Ce serait une voie intelligente pour atteindre vos objectifs à long terme ici.
Il y a toujours le Marketplace si vous voulez payer un développeur pour lui redonner vie en attendant. Mais vous pourriez finir par devoir le faire plusieurs fois ou accepter un contrat de maintenance.
Je suppose que la réponse est Non ? J’aimerais migrer vers les réactions et essayer de trouver les plus populaires…
J’imagine que ce serait possible car ils seraient stockés quelque part dans la base de données. Malheureusement, je n’ai pas ce plugin installé sur mon site de test pour vérifier les spécificités. Existe-t-il une table discourse-retort-retorts ou similaire ?
Voici comment obtenir une chaîne de caractères séparée par des | pour les réponses que vous utilisez actuellement :
# ./launcher enter app
# rails c
retorts = {}
PostDetail.where(extra: 'retort').each do |p|
retort = p.key.split('|').first
(retorts[retort] ||= []) << p
end
retorts.length
retorts.keys.join('|')
Cela vous donnera :
- D’abord le nombre d’emojis de réponse uniques utilisés
- Ensuite, les réponses dans un format que vous pourriez coller dans la configuration des réactions, peut-être après avoir coupé si c’est trop long pour l’interface des réactions.
Pour moi, j’obtiens cette chaîne :
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
Si vous souhaitez copier une liste de réponses existantes dans un message sur Discourse pour discuter de ce qu’il faut conserver lors de la migration vers les réactions, vous pourriez plutôt utiliser ceci :
":" + retorts.keys.join(': :') + ':'
Pour moi, c’est actuellement cet ensemble :
“
:微笑:
”
Pour obtenir une liste à puces des emojis avec le nombre d’occurrences de chacun :
retorts.keys.sort.each do |k|
puts "* :#{k}: #{retorts[k].length}"
end
Je ne vais pas coller la liste complète des emojis à puces, mais elle commence comme ceci :
161
1
1
1
9
2
2
23
3
Si vous voulez voir chaque message existant pour chaque emoji :
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
C’est beaucoup trop long à coller ici !
Ce que je ne sais pas, c’est comment migrer toutes ces réponses, ou une partie d’entre elles, vers les réactions. Il n’y a aucune mention de réponse dans le plugin de réactions, donc il ne le fait pas automatiquement. J’ai 927 réactions avec 116 emojis uniques que j’aimerais migrer vers les réactions.
Je m’attends à devoir gérer cela à un moment donné, de préférence avant que Retort ne cesse tout simplement de fonctionner ; si j’implémente la migration, je prévois de la documenter ici. Mais au moins savoir ce que vous avez pourrait vous aider.
Dans l’écriture de code expérimental pour migrer Retort vers Reactions, j’ai découvert que les Retorts ne sont pas mis à jour lorsque les noms d’utilisateur sont modifiés.
Je pense que cela ne sera pas vrai avec Reactions car PostActions se joint à des enregistrements d’utilisateurs réels, plutôt que d’enregistrer des noms d’utilisateur dans un blob JSON dans PostDetail.
En général, si quelqu’un décidait d’adopter et de maintenir Retort, il devrait envisager de migrer de PostDetail vers PostActions en suivant la manière dont Reactions a été fait.
De même, il ne reconnaît pas lorsque des publications sont supprimées.
Mon Script framework to rearrange topics and categories a une nouvelle fonction qui va un peu au-delà du réarrangement des sujets et des catégories !
Je me souviens généralement de prévenir que je ne connais ni le ruby ni le ruby on rails, donc mon code est idiosyncratique plutôt qu’idiomatique. Mais il semble fonctionner jusqu’à présent dans mes tests !
def migrateRetortToReactions(allowed:, likes: nil, emojimap: nil)
# migrer autant que possible sans remplacer les likes existants
# c'est une conversion nécessairement avec perte, et elle est cohérente uniquement par l'ordre de PostDetail
# aucune tentative n'est faite pour préférer un enregistrement PostDetail à un autre
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 incohérent par rapport à la suppression
$stderr.puts sprintf("Impossible de trouver le post pour %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? # le changement de nom d'utilisateur ou la suppression d'utilisateur laisse des Retorts orphelins
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("Ajout d'un like pour Retort %s pour l'utilisateur %s dans %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("Conversion de Retort %s en Reaction %s pour l'utilisateur %s dans %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("Ignoré Retort non mappé %s pour l'utilisateur %s dans %s", emoji, user, p.url)
end
end
end
end
J’utilise le framework que j’ai construit pour fournir une configuration yaml qui ressemble à ceci :
- 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
Cependant, vous pourriez simplement envelopper cela dans un script ruby, y compris en transformant ces arguments en code ruby littéral, le placer dans le répertoire script/ et l’exécuter.
Salut à tous, comme discuté dans le sujet ci-dessus, j’ai déjà écrit une fonctionnalité de migration de Retort vers Reactions, y compris une interface d’administration.
Pour qu’elle soit prête pour la production, les mainteneurs de Reactions devront apporter une légère modification pour améliorer l’abstraction du code dans le plugin Reactions.
La prise en charge d’une migration de niveau production entre deux plugins comme celui-ci nécessite un contrôle qualité important, sinon des problèmes comme celui-ci peuvent facilement survenir.
Je suis désolé ! J’avais manqué ces publications et je n’avais regardé que dans la branche principale. C’est un long fil de discussion…
Je suis d’accord. Je l’ai complètement contourné. C’est plus que juste ReactionManager.toggle! — il faut vraiment passer par created_at, n’est-ce pas ?
Le passage à Reactions change vraiment la sémantique de « j’aime » car on ne peut pas revenir en arrière lorsque quelqu’un modifie son message. Je n’aurais pas fait le même choix d’implémentation. ![]()
Quoi qu’il en soit, ce que je veux faire, c’est piloter cela à partir d’un script, et je n’ai aucun intérêt à le piloter à partir d’une interface utilisateur. Je ne suis pas le public cible de l’interface utilisateur, donc peut-être que mon hack disponible ne fait pas de mal.
Absolument, je ne voulais pas vous décourager de l’écrire pour vos propres besoins, mais je ne conseillerais pas à d’autres sites de l’utiliser à moins qu’ils ne soient familiers avec le code et la structure des données.
Le résultat net est que le plugin Reactions n’est actuellement pas écrit d’une manière propice à une migration stable qui fonctionnera de manière fiable dans différents environnements.
Si quelqu’un souhaite migrer de Retort vers Reactions, Pavilion s’en charge manuellement sur une base contractuelle (envoyez un e-mail à contact@pavilion.tech ou envoyez-moi un message privé). Si le plugin Reactions est mis à jour pour permettre des migrations généralisées, nous terminerons le travail de migration pour le rendre librement disponible.
Aha. Cela répond à certaines de mes questions. Il est difficile de comprendre 450 publications sur 7 ans.
Donc, si je comprends bien, ce qui « doit » se produire (tout le monde est invité à fournir sa propre définition de « doit ») est d’étendre d’une manière ou d’une autre Reactions afin qu’elle puisse gérer plus proprement la migration des données vers elle et également fournir les fonctionnalités qui lui manquent ?
Quelle est l’ampleur de ce travail en termes d’heures ou de dollars, selon une estimation approximative ?
Ceci est toujours globalement exact.

Si l’opportunité d’une PR est réaliste, je le ferais probablement pour une bonne bouteille de rouge. C’est vendredi soir après tout.
Mais, plus sérieusement, ce dont nous parlons ici est un refactoring mineur du plugin Reactions ReactionManager. Ce type de travail n’est généralement pas accepté via PR. Il faudrait l’adhésion des mainteneurs de Reactions.
Je pense que vous voudrez également vous assurer que les likes sont silencieux et que created_at est géré pour les likes et les réactions ; sinon, les utilisateurs seront spammés de notifications par la migration. (J’ai vu cela sur mon site de test pour ma propre connexion.)
Pour une raison quelconque, même avec created_by géré, je déclenche toujours le maximum de likes out of love, et je n’ai pas enquêté davantage, car j’ai supprimé toutes les autres notifications.
@joffreyjaffeux y a-t-il une raison de ne pas exposer la fonctionnalité nécessaire pour une migration propre ?
J’ai juste migré vers Reactions (parce que je suppose que c’est officiel et tout…) mais je détesterais perdre toutes les données de rétorques précédentes.
Je suis désolé, mais fournir une migration stable n’est pas possible pour le moment pour les raisons mentionnées ci-dessus.
Eh bien, c’est arrivé, je n’ai pas pu mettre à jour discourse à cause du plugin retort.
Voici l’erreur de migration de base de données que j’ai obtenue :
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.
J’ai utilisé ce script comme base pour mon propre code de migration. Voici ce que j’ai fait.
- Pour que discourse fonctionne à nouveau, j’ai dû remplacer la « version » dans le fichier modèle .yml par un commit d’il y a environ deux semaines dans le dépôt discourse.
- Reconstruire avec le plugin de réactions ajouté pour remettre le site en ligne.
- J’ai configuré le plugin de réactions avec le même ensemble de réactions que retort. Je n’utilise aucune réaction qui pourrait être interprétée comme un like.
- J’ai utilisé le script de @mcdanlj légèrement modifié avec les étapes suivantes (car je voulais migrer tous les retorts et j’avais déjà un mappage 1-à-1 entre les retorts et les réactions) :
- Exécuter
./launcher enter app - Exécuter
rails c - Coller ce qui suit (il semble que la console rails renverra le code avec des changements de ligne incorrects, j’ai ajouté des doubles changements de ligne mais cela n’a pas vraiment changé la sortie, mais si quelqu’un obtient une erreur de syntaxe avec le code suivant, ajoutez une ligne supplémentaire après chaque ligne) :
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
- À ce stade, j’ai effectué une sauvegarde du site au cas où.
- Ensuite, exécutez
migrateRetortToReactionsqui devrait prendre un certain temps. Pour moi, je n’ai vu ni rencontré de problèmes. Après avoir exécuté la console, il semble qu’elle affiche tous les objets modifiés, alors appuyez surqpour quitter. - Maintenant, sur le site, les données devraient être migrées correctement.
- Comme étape finale, vous devez exécuter :
PostDetail.where(extra: "retort").destroy_allqui supprimera les données de retort. - Maintenant, j’ai pu reconstruire mon site avec la dernière version de discourse et sans le plugin retort.
Donc, dans l’ensemble, pas si difficile à migrer, mais c’était assez effrayant, et comme discuté précédemment, cela écrase les likes par des réactions sur les posts qui avaient à la fois des likes et des retorts par le même utilisateur.
D’accord ! Plusieurs réactions et la possibilité de choisir parmi toutes les réactions sont indispensables pour ma communauté. Les gens s’y attendent de la part de l’univers des serveurs de discussion Discord, donc revenir en arrière sur cette fonctionnalité dans ma communauté est hors de question. Heureusement, ce plugin ne m’a pas encore posé de problème, mais je me résigne à la réalité et je compte les jours. J’espère que la solution souhaitée viendra soit de la communauté tierce, soit officiellement de Discourse dans les six prochains mois. Sinon, je serais obligé de maintenir mon forum à une version de build plus ancienne indéfiniment si ce plugin venait à casser les mises à jour par la suite.
Avec les nouveaux changements d’Ember 5, Retort est maintenant obsolète. Exploration des options pour préserver sa fonctionnalité.