Retórica de Discourse

Abrí una nueva solicitud Support multiple-reactions per post (Retort style) sobre múltiples reacciones por publicación, ya que el otro enlace es solo para ofrecer más opciones de reacción para la única reacción que permite Discourse Reactions.

3 Me gusta

El plugin Retort no es oficial, por lo que no tenemos control sobre cuándo deja de ser desarrollado y mantenido activamente por la comunidad. :man_shrugging: Lo mejor que podemos hacer es intentar mantener a la gente informada siempre que sea posible para que tengan tiempo de encontrar una alternativa (o al menos avisar a sus miembros para intentar suavizar la decepción).

Esperemos que esas dos solicitudes de #características se adopten en el plugin de #reacciones en algún momento, pero todavía están en la etapa de ‘buenas ideas’. Pero cruzaré los dedos. :crossed_fingers:

3 Me gusta

Entiendo tu punto de vista. La realidad es que ni James ni yo hemos tenido tiempo para dar soporte adecuado a Retort durante un tiempo. Notarás que el último commit en el repositorio tiene más de un año (realizado por mí el 21 de julio de 2021). Es genial que el plugin haya seguido funcionando tanto tiempo y es un testimonio de la calidad del trabajo que James puso en su desarrollo.

Cuando digo que no tengo tiempo, créeme, ¡ojalá lo tuviera! Me entristece cada vez que tengo que tomar una de estas decisiones (como con el Plugin de Páginas de Destino). No creé Retort, pero he invertido tiempo en él. Cuando decides retirar algo, es como aceptar que algo que has creado o amado, y con lo que has pasado muchas horas, días y semanas de tu vida, debe morir. Sé que fue una decisión difícil para James cuando sintió que tenía que pasar a otras cosas.

En contraste, el Plugin de Reacciones está siendo mantenido por Discourse.org, una organización de más de 60 personas, de forma activa. Se está utilizando en varios de los servidores que usan los clientes de Discourse.org. Sí, todavía no tiene las mismas características que Retort, pero te instaría a que persigas el desarrollo de esa característica como una vía. Quizás podrías convencer a alguien como yo, o a otro miembro de Pavilion, para que haga un PR de una característica faltante en el plugin. Esa sería una vía inteligente para lograr tus objetivos a largo plazo aquí.

7 Me gusta

Siempre está Marketplace si quieres pagarle a un desarrollador para que lo reviva mientras tanto. Pero es posible que tengas que hacer esto varias veces o acordar un contrato de mantenimiento.

2 Me gusta

Supongo que la respuesta es No? Me gustaría migrar a reacciones y tratar de encontrar las populares…

1 me gusta

Me imagino que sería posible ya que se almacenarán en la base de datos en algún lugar. Desafortunadamente, no tengo este plugin instalado en mi sitio de prueba para verificar los detalles. ¿Hay una tabla discourse-retort-retorts o similar?

2 Me gusta

Aquí tienes cómo obtener una cadena separada por | para las réplicas que tienes actualmente en uso:

# ./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('|')

Eso te da:

  • Primero el número de emojis de réplica únicos utilizados
  • Luego las réplicas en un formato que podrías pegar en la configuración de Reacciones, quizás después de recortar si es demasiado largo para la interfaz de Reacciones.

Para mí, obtengo esta cadena:

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 deseas copiar una lista de réplicas existentes en una publicación en Discourse para discutir cuáles conservar al migrar a Reacciones, podrías usar esto en su lugar:

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

Para mí, actualmente es este conjunto:

: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:

Para obtener una lista con viñetas de emojis con el número de instancias de cada uno:

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

No pegaré la lista completa de emojis con viñetas, pero comienza así:

  • :+1: 161
  • :-1: 1
  • :100: 1
  • :arrow_right_hook: 1
  • :astonished: 9
  • :blush: 2
  • :boom: 2
  • :brain: 23
  • :bulb: 3

Si quieres ver cada publicación que existe para cada 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

¡Eso es demasiado largo para pegarlo aquí!

Lo que no sé es cómo migrar todas, o algunas, de esas réplicas a reacciones. No hay mención de réplica en el plugin de reacciones, por lo que no lo hace automáticamente. Tengo 927 reacciones con 116 emojis únicos que me gustaría migrar a reacciones.

Espero que me enfrente a esto en algún momento, preferiblemente antes de que Retort deje de funcionar; si implemento la migración, planeo documentarla aquí. Pero al menos saber lo que tienes podría ayudarte.

6 Me gusta

Al escribir código experimental para migrar Retort a Reactions, he descubierto que los Retorts no se actualizan cuando se cambian los nombres de usuario.

Creo que esto no será cierto con Reactions porque PostActions se une a registros de usuario reales, en lugar de registrar nombres de usuario en un blob JSON en PostDetail.

En general, si alguien decidiera adoptar y mantener Retort, debería considerar migrar de PostDetail a PostActions siguiendo cómo se hizo Reactions.

De manera similar, no reconoce cuándo se eliminan las publicaciones.

Mi Script framework to rearrange topics and categories ha crecido una nueva función que va un poco más allá de reorganizar temas y categorías.

Normalmente recuerdo advertir que no sé ruby ni ruby on rails, así que mi código es idiosincrásico en lugar de idiomático. ¡Pero parece que funciona hasta ahora en mis pruebas!

  def migrateRetortToReactions(allowed:, likes: nil, emojimap: nil)
    # migrar siempre que sea posible sin anular los likes existentes
    # esta es una conversión necesariamente con pérdida de datos, y es consistente solo por el orden de PostDetail
    # no se intenta preferir un registro de PostDetail sobre otro
    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 no es consistente con respecto a la eliminación
        $stderr.puts sprintf("No se pudo encontrar la publicación para %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? # el nombre de usuario cambiado o el usuario eliminado dejan Retorts huérfanos
        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("Añadiendo like para Retort %s para el usuario %s en %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("Convirtiendo Retort %s a Reaction %s para el usuario %s en %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("Ignorando Retort no mapeado %s para el usuario %s en %s", emoji, user, p.url)
        end
      end
    end
  end

Uso el framework que construí para proporcionar una configuración yaml que se ve así:

- 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

Sin embargo, podrías simplemente envolver eso en un script de ruby, incluyendo hacer que esos argumentos sean código ruby literal, colocarlo en el directorio script/ y ejecutarlo.

2 Me gusta

Hola chicos, como se discutió en el tema anterior, ya he escrito una función de migración de Retort a Reactions, incluida una interfaz de administración.

Para que esté listo para producción, los mantenedores de Reactions deberán hacer un pequeño cambio para mejorar la abstracción del código en el plugin Reactions.

Soportar una migración a nivel de producción entre dos plugins como este requiere un control de calidad significativo, de lo contrario, problemas como este pueden ocurrir fácilmente.

4 Me gusta

¡Lo siento! Me había perdido esas publicaciones y solo había mirado en la rama principal. Es un hilo largo…

Estoy de acuerdo. Lo esquivé por completo. Es más que solo ReactionsManager.toggle!, ¿verdad? Realmente necesita pasar por created_at, ¿no?

El cambio a Reactions realmente cambia la semántica de “me gusta” porque no puedes retractarte cuando alguien edita su publicación. No habría tomado la misma decisión de implementación. :frowning:

En cualquier caso, lo que quiero hacer es controlar esto desde un script, y no tengo ningún interés en controlarlo desde una interfaz de usuario. No soy el público objetivo de la interfaz de usuario, así que tal vez mi hack no haga daño.

1 me gusta

Por supuesto, no quise desanimarte a escribirlo para tus propios fines, pero no aconsejaría a otros sitios que lo usen a menos que estén familiarizados con el código y la estructura de datos.

La conclusión es que el complemento Reactions no está escrito actualmente de una manera que propicie una migración estable que funcione de manera confiable en diferentes entornos.

Si alguien desea migrar de Retort a Reactions, Pavilion se encarga de estas manualmente por contrato (envíe un correo electrónico a contact@pavilion.tech o envíeme un mensaje privado). Si el complemento Reactions se actualiza para permitir migraciones generalizadas, completaremos el trabajo de migración para que esté disponible de forma gratuita.

2 Me gusta

Ajá. Esto responde a algunas preguntas que tenía. Es difícil dar sentido a 450 publicaciones a lo largo de 7 años.

Entonces, ¿entiendo que lo que “necesita” suceder (cualquiera es bienvenido a proporcionar su propia definición de “necesita”) es extender de alguna manera Reactions para que pueda manejar de manera más limpia la migración de datos y también proporcionar las características que le faltan?

¿Qué tan grande es ese trabajo en una estimación aproximada de horas o dólares?

Esto sigue siendo en gran medida exacto.


Si la oportunidad para una PR existe de manera realista, probablemente lo haría por una buena botella de tinto. Es viernes por la noche, después de todo.

Pero, hablando un poco más en serio, de lo que estamos hablando aquí es de una refactorización menor del ReactionManager del plugin Reactions. Ese tipo de trabajo normalmente no se acepta a través de PR. Se necesitaría la aprobación de los mantenedores de Reactions.

Creo que también querrás asegurarte de que los “likes” sean silent y que created_at se maneje para los “likes” y las reacciones; de lo contrario, los usuarios se verán bombardeados con notificaciones de la migración. (Vi esto en mi sitio de prueba para mi propio inicio de sesión).

Por alguna razón, incluso con created_by manejado, todavía activo el máximo de “likes” de “out of love”, y no investigué más, porque me deshice de todas las demás notificaciones.

@joffreyjaffeux ¿alguna razón para no exponer la funcionalidad necesaria para una migración limpia?

Me he cambiado a Reactions (porque supongo que es oficial y todo…) pero odiaría perder todos los datos de retort anteriores.

Lo siento, pero no es posible proporcionar una migración estable en este momento por las razones mencionadas anteriormente.

Bueno, finalmente sucedió, no pude actualizar discourse debido al plugin retort.

Este es el error de migración de base de datos que obtuve:

no se pudo crear el índice único "index_post_details_on_post_id_and_key_ccnew_ccnew" DETAIL: La clave (post_id, key)=(30297, +1|retort) está duplicada.

Utilicé este script como base para mi propio código de migración. Esto es lo que hice.

  • Para que discourse volviera a funcionar, tuve que anular la “versión” en el archivo de plantilla .yml a un commit de hace aproximadamente dos semanas en el repositorio de discourse.
  • Reconstruí con el plugin de reacciones añadido para que el sitio volviera a funcionar.
  • Configuré el plugin de reacciones con el mismo conjunto de reacciones que retort. No utilizo ninguna reacción que pueda interpretarse como “me gusta”.
  • Utilicé el script de @mcdanlj un poco modificado con los siguientes pasos (ya que quería migrar todos los retort y ya tenía un mapeo de 1 a 1 entre retort y reacciones):
  • Ejecutar ./launcher enter app
  • Ejecutar rails c
  • Pegar lo siguiente (parece que la consola de rails repetirá el código con cambios de línea incorrectos, añadí dobles saltos de línea pero eso no cambió realmente la salida, pero si alguien obtiene un error de sintaxis con el siguiente código, añada un salto de línea adicional después de cada línea):
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 no es consistente con respecto a la eliminación
      $stderr.puts sprintf("No se pudo encontrar la publicación para %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? # el nombre de usuario cambiado o el usuario eliminado deja Retorts huérfanos
      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("Convirtiendo Retort %s a Reacción %s para el usuario %s en %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
  • En este punto hice una copia de seguridad del sitio por si acaso.
  • Luego ejecute migrateRetortToReactions que debería tardar un tiempo. En mi caso, no vi ni me encontré con ningún problema. Después de ejecutarlo, la consola parece mostrar todos los objetos cambiados, así que presione q para salir.
  • Ahora en el sitio debería ser el caso de que los datos se migren correctamente.
  • Como paso final, debe ejecutar: PostDetail.where(extra: "retort").destroy_all que eliminará los datos de retort.
  • Ahora pude reconstruir mi sitio con la última versión de discourse y sin el plugin retort.

En resumen, no es tan difícil de migrar, pero fue bastante aterrador, y como se discutió anteriormente, esto sobrescribe los “me gusta” con reacciones en las publicaciones que tenían tanto “me gusta” como “retorts” por el mismo usuario.

6 Me gusta

¡De acuerdo! Múltiples reacciones y poder elegir entre todas las reacciones es imprescindible para mi comunidad. La gente ha llegado a esperarlo del mundo de los servidores de chat de Discord, por lo que revertir esa función en mi comunidad no es una opción. Afortunadamente, este plugin aún no se ha roto para mí, pero estoy resignado a la realidad de que estoy contando lentamente los días. Espero que la solución deseada provenga de la comunidad de terceros o de Discourse oficialmente en los próximos seis meses. De lo contrario, me vería obligado a mantener mi foro en una versión de compilación anterior indefinidamente si resulta que este plugin rompe las actualizaciones en el futuro.

1 me gusta

Con los nuevos cambios de Ember 5, Retort está muerto. Explorando opciones para preservar su funcionalidad.

1 me gusta