Retorno do Discurso

Abri uma nova solicitação Support multiple-reactions per post (Retort style) sobre multiple-reactions-per-post, já que o outro link é apenas para oferecer mais opções de reação para a única reação que o Discourse Reactions permite.

3 curtidas

O plugin Retort não é um #oficial, então não temos controle sobre quando ele para de ser ativamente desenvolvido e mantido pela comunidade. :man_shrugging: O máximo que podemos fazer é tentar manter as pessoas informadas sempre que possível para que tenham tempo de encontrar uma alternativa (ou pelo menos avisar seus membros para tentar amenizar a decepção).

Esperamos que essas duas Feature requests sejam adotadas no plugin reactions em algum momento, mas, até agora, elas ainda estão no estágio de ‘boas ideias’. Mas estou na torcida. :crossed_fingers:

3 curtidas

Entendo seu ponto de vista. A realidade é que nem eu nem James tivemos tempo de dar suporte adequado ao Retort por algum tempo. Você notará que o último commit no repositório é de mais de um ano atrás (feito por mim em 21 de julho de 2021). É ótimo que o plugin tenha continuado funcionando por tanto tempo e isso é um testemunho da qualidade do trabalho que James colocou em sua construção.

Quando digo que não tenho tempo, acredite, eu gostaria de ter! Sinto-me triste toda vez que tenho que tomar uma dessas decisões (como com o Landing Pages Plugin). Eu não criei o Retort, mas investi tempo nele. Quando você decide desativar algo, é como aceitar que algo que você criou ou amou, e com o qual passou muitas horas, dias e semanas de sua vida, deve morrer. Sei que foi uma decisão difícil para James tomar quando sentiu que precisava seguir em frente para outras coisas.

Em contraste, o Reactions Plugin está sendo mantido pelo Discourse.org, uma organização com mais de 60 pessoas, de forma ativa. Ele está em uso em vários servidores usados pelos clientes do Discourse.org. Sim, ele ainda não tem os mesmos recursos que o Retort, mas eu o incentivaria a buscar o desenvolvimento desse recurso como uma via. Talvez você pudesse convencer alguém como eu, ou outro membro do Pavilion, a fazer um PR de um recurso que falta no plugin. Essa seria uma via inteligente para atingir seus objetivos de longo prazo aqui.

7 curtidas

Sempre existe o Marketplace se você quiser pagar a um desenvolvedor para trazê-lo de volta à vida enquanto isso. Mas você pode acabar tendo que fazer isso várias vezes ou concordar com um contrato de manutenção.

2 curtidas

Acho que a resposta é Não? Eu gostaria de migrar para reações e tentar encontrar as populares…

1 curtida

Imagino que seria possível, pois eles serão armazenados no banco de dados em algum lugar. Infelizmente, não tenho este plugin instalado no meu site de teste para verificar os detalhes. Existe uma tabela discourse-retort-retorts ou algo semelhante?

2 curtidas

Aqui está como obter uma string separada por | para as respostas que você tem em 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('|')

Isso lhe dará:

  • Primeiro, o número de emojis de resposta únicos usados
  • Em seguida, as respostas em um formato que você poderia colar na configuração de Reações, talvez após aparar se for muito longo para funcionar na interface de Reações.

Para mim, obtenho esta string:

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

Se você quiser copiar uma lista de respostas existentes para uma postagem no Discourse para discutir o que manter ao migrar para Reações, você pode usar isto:

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

Para mim, atualmente é 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 obter uma lista com marcadores de emojis com o número de instâncias de cada um:

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

Não vou colar a lista completa de emojis com marcadores, mas começa assim:

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

Se você quiser ver cada postagem 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

Isso é muito longo para colar aqui!

O que eu não sei é como migrar todas — ou algumas — dessas respostas para reações. Não há menção de resposta no plugin de reações, então ele não faz isso automaticamente. Tenho 927 reações com 116 emojis únicos que gostaria de migrar para reações.

Espero que eu enfrente isso em algum momento, de preferência antes que o Retort simplesmente pare de funcionar; se eu implementar a migração, planejo documentá-la aqui. Mas pelo menos saber o que você tem pode ajudar você.

6 curtidas

Ao escrever um código experimental para migrar Retort para Reactions, descobri que os Retorts não são atualizados quando os nomes de usuário são alterados.

Acho que isso não será verdade com Reactions porque PostActions se une a registros de usuário reais, em vez de registrar nomes de usuário em um blob JSON em PostDetail.

Em geral, se alguém decidisse adotar e manter o Retort, deveria considerar a migração de PostDetail para PostActions, seguindo como o Reactions foi feito.

Da mesma forma, ele não reconhece quando as postagens são excluídas.

Meu Script framework to rearrange topics and categories cresceu uma nova função que vai um pouco além de reorganizar tópicos e categorias!

Eu geralmente me lembro de avisar que não sei ruby ou ruby on rails, então meu código é idiossincrático em vez de idiomático. Mas parece que tem funcionado nos meus testes!

  def migrateRetortToReactions(allowed:, likes: nil, emojimap: nil)
    # migra onde possível sem substituir curtidas existentes
    # esta é uma conversão necessariamente com perdas, e é consistente apenas pela ordem de PostDetail
    # nenhuma tentativa é feita para preferir um registro PostDetail em detrimento de outro
    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 não consistente em relação à exclusão
        $stderr.puts sprintf("Não foi possível encontrar a postagem 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? # nome de usuário alterado ou usuário excluído deixa Retorts órfãos
        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("Adicionando curtida para Retort %s para o usuário %s em %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("Convertendo Retort %s para Reação %s para o usuário %s em %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 não mapeado %s para o usuário %s em %s", emoji, user, p.url)
        end
      end
    end
  end

Eu uso o framework que construí para fornecer uma configuração yaml que se parece com isto:

- 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

No entanto, você poderia simplesmente empacotar isso em um script ruby, incluindo a criação desses argumentos como código ruby literal, colocá-lo no diretório script/ e executá-lo.

2 curtidas

Olá pessoal, como discutido no tópico acima, já escrevi um recurso de migração do Retort para Reactions, incluindo uma interface de administração.

Para que esteja pronto para produção, os mantenedores do Reactions precisarão fazer uma pequena alteração para melhorar a abstração do código no plugin Reactions.

O suporte a uma migração de nível de produção entre dois plugins como este requer garantia de qualidade significativa, caso contrário, problemas como este podem ocorrer facilmente.

4 curtidas

Desculpe! Eu perdi essas postagens e apenas olhei no branch principal. É um tópico longo…

Concordo. Eu o contornei completamente. É mais do que apenas ReactionManager.toggle! — realmente precisa passar por created_at, não é?

A mudança para Reações realmente altera a semântica de “curtir” porque você não pode voltar atrás quando alguém edita sua postagem. Eu não teria feito a mesma escolha de implementação. :frowning:

De qualquer forma, o que quero fazer é controlar isso a partir de um script, e não tenho o menor interesse em controlá-lo a partir de uma interface de usuário. Eu não sou o público-alvo da interface de usuário, então talvez meu hack disponível não prejudique.

1 curtida

De qualquer forma, não tive a intenção de desencorajá-lo a escrevê-lo para seus próprios fins, mas eu não aconselharia outros sites a usá-lo, a menos que estejam familiarizados com o código e a estrutura dos dados.

O ponto principal é que o Reactions Plugin não está atualmente escrito de uma forma propícia a uma migração estável que funcione de forma confiável em diferentes ambientes.

Se alguém desejar migrar do Retort para o Reactions, o Pavilion está lidando com isso manualmente, mediante contrato (envie um e-mail para contact@pavilion.tech ou me envie uma mensagem privada). Se o Reactions Plugin for atualizado para permitir migrações generalizadas, nós concluiremos o trabalho de migração para disponibilizá-lo gratuitamente.

2 curtidas

Aha. Isso responde a algumas perguntas que eu tinha. É difícil dar sentido a 450 posts ao longo de 7 anos.

Então, eu entendo que o que “precisa” acontecer (qualquer um é bem-vindo a fornecer sua própria definição de “precisa”) é estender de alguma forma as Reações para que ele possa lidar de forma mais limpa com a migração de dados para ele e também fornecer recursos que estão faltando?

Qual o tamanho desse trabalho em alguma estimativa maluca de horas ou dólares?

Isso ainda está amplamente correto.


Se a oportunidade para um PR existir realisticamente, eu provavelmente faria isso por uma boa garrafa de vinho tinto. Afinal, é sexta à noite.

Mas, falando um pouco mais sério, o que estamos discutindo aqui é um pequeno refatoramento do plugin de Reações ReactionManager. Esse tipo de trabalho normalmente não é aceito via PR. Seria necessário o aval dos mantenedores de Reações.

Acho que você também vai querer garantir que os likes sejam silenciosos e que created_at seja tratado para likes e reações; caso contrário, os usuários serão bombardeados com notificações da migração. (Eu vi isso no meu site de teste para meu próprio login.)

Por algum motivo, mesmo com created_by tratado, ainda aciono o limite máximo de likes out of love, e não investiguei mais a fundo, porque me livrei de todas as outras notificações.

@joffreyjaffeux algum motivo para não expor a funcionalidade necessária para uma migração limpa?

Acabei de migrar para Reactions (porque acho que é oficial e tudo mais…) mas odiaria perder todos os dados anteriores de retort.

Sinto muito, mas fornecer uma migração estável não é possível no momento pelas razões mencionadas acima.

Bem, aconteceu, não consegui atualizar o discourse por causa do plugin retort.

Este é o erro de migração de banco de dados que recebi:

não foi possível criar o índice exclusivo “index_post_details_on_post_id_and_key_ccnew_ccnew” DETAIL: Chave (post_id, key)=(30297, +1|retort) está duplicada.

Usei este script como base para meu próprio código de migração. Veja o que fiz.

  • Para fazer o discourse funcionar novamente, tive que substituir a “versão” no arquivo de modelo .yml por um commit de cerca de duas semanas atrás no repositório do discourse
  • Reconstruí com o plugin de reações adicionado para trazer o site de volta
  • Configurei o plugin de reações com o mesmo conjunto de reações do retort. Não uso nenhuma reação que possa ser interpretada como “like”
  • Usei o script de @mcdanlj um pouco modificado com os seguintes passos (já que eu queria migrar todos os retorts e eu tinha um mapeamento de 1 para 1 entre retorts e reações):
  • Execute ./launcher enter app
  • Execute rails c
  • Cole o seguinte (parece que o console do rails ecoará o código com alterações incorretas de linha, adicionei alterações duplas de linha, mas isso não mudou realmente a saída, mas se alguém tiver um erro de sintaxe com o código a seguir, adicione uma linha extra após cada linha):
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 não consistente em relação à exclusão
      $stderr.puts sprintf("Não foi possível encontrar post 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? # nome de usuário alterado ou usuário excluído deixa Retorts órfãos
      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("Convertendo Retort %s para Reação %s para o usuário %s em %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
  • Neste ponto, fiz um backup do site, por precaução
  • Em seguida, execute migrateRetortToReactions, que deve demorar um pouco. Para mim, não vi nem encontrei problemas. Após a execução, o console parece mostrar todos os objetos alterados, então pressione q para sair
  • Agora, no site, os dados devem ter sido migrados corretamente
  • Como um passo final, você precisa executar: PostDetail.where(extra: "retort").destroy_all, que excluirá os dados do retort
  • Agora pude reconstruir meu site com a versão mais recente do discourse e sem o plugin retort

Portanto, no geral, não é tão difícil de migrar, mas foi bastante assustador, e como discutido anteriormente, isso substitui os likes por reações em posts que tinham ambos os likes e retorts pelo mesmo usuário.

6 curtidas

Concordo! Múltiplas reações e a possibilidade de escolher entre todas as reações são essenciais para a minha comunidade. As pessoas passaram a esperar isso do mundo dos servidores de chat do Discord, então reverter esse recurso na minha comunidade está fora de questão. Felizmente, este plugin ainda não quebrou para mim, mas estou resignado à realidade de que estou lentamente contando os dias. Espero que a solução desejada venha da comunidade de terceiros ou oficialmente do Discourse nos próximos seis meses. Caso contrário, serei forçado a manter meu fórum em uma versão de build mais antiga indefinidamente se acabar sendo que este plugin quebra atualizações futuramente.

1 curtida

Com as novas alterações do Ember 5, o Retort está agora obsoleto. Explorando opções para preservar sua funcionalidade.

1 curtida