Opcionalmente encadeando posts ao tópico principal na integração do Slack

No trabalho, usamos muito o Slack. Há algum conteúdo que precisa estar acessível no Slack, mas que também deve ser organizado e pesquisável — duas coisas em que o Discourse se destaca. Já testamos algumas opções semelhantes a wikis, mas todas acabam ficando desatualizadas, em parte devido à falta de integração com o Slack. Por isso, estou liderando uma avaliação do Discourse para rodar em paralelo e conectado ao nosso Slack existente, já que eu já administro um fórum Discourse comunitário. :smiling_face:

No entanto, temos muitos canais que usam threads de forma intensiva. Isso inclui o canal de maior prioridade no Slack para integração bidirecional (watch e post) entre o Discourse e o Slack.

Seria problemático para o plugin de integração com chat ter um modo não padrão que publicasse novos tópicos como mensagens no Slack, armazenasse a associação entre o ID da mensagem no Slack e o tópico, e então enviasse novos comentários sobre esse tópico ao Slack como mensagens em thread? Para o meu caso de uso, isso pode ser o principal diferencial entre o sucesso e o fracasso.

Atualização: Para o meu caso de uso, isso seria uma opção de watch, não uma configuração geral de chat do site com o Slack, pois “preferir threads” ou “não preferir threads” é uma preferência por canal, baseada no propósito (e nos participantes típicos) de cada canal do Slack.

4 curtidas

Isso parece uma ideia legal! Adicionar isso ao plugin seria certamente pr-welcome

Só confirmando… por “postar”, você se refere ao recurso existente de postagem de transcrição? Ou você está tentando fazer com que uma thread do Slack “sincronize” com um tópico do Discourse? Acredito que a segunda opção seja bastante complicada de implementar corretamente e provavelmente não se encaixaria no plugin de integração de chat.

1 curtida

Não, não estou tentando sincronizar bidirecionalmente um único tópico para que seja possível postar de qualquer lado e ter a reflexão no outro. Já fui responsável por implementar sincronização totalmente bidirecional para sincronização ativa-ativa entre dois domínios muito ativos e estou plenamente ciente das oportunidades de errar nesse cenário. :smiling_face:

Nosso cenário é um canal em que:

  • Respostas em tópicos são a norma, pois o canal tende a reunir conversas simultâneas sobre tópicos não relacionados (o canal é dedicado a um propósito de negócio, não a um tópico; a alternativa impraticável seria convidar metade da engenharia para novos canais temporários criados uma dúzia de vezes por dia)
  • Muitas, mas não todas, dessas conversas em tópicos devem ser identificadas como respostas a perguntas que alguém, mais tarde, desejará consultar, e a integração usada para promovê-las como confiáveis na categoria associada no Discourse (alguém como eu, curando ativamente respostas úteis)
  • Novos tópicos nessa categoria associada no Discourse devem resultar em postagens no Slack nesse canal do Slack
    • Comentários adicionais nesses novos tópicos devem ser postados no Slack em um tópico seguindo a primeira postagem inicial no Slack
  • Nossos usuários são orientados a pesquisar primeiro no Discourse antes de perguntar no Slack

Além disso, o fato de você fazer essa pergunta me faz pensar que, como recurso relacionado, seria ótimo ter a capacidade, ao resumir um tópico do Slack em uma postagem no Discourse, de a integração postar um ponteiro para o novo tópico do Discourse no final do tópico original do Slack que acabou de ser resumido. Isso seria útil para nós manter a conversa em um só lugar.

Isso está, na verdade, ligado à ideia original do recurso, porque, se tivéssemos ambos, faria sentido que, em vez de postar uma nova mensagem no Slack ao resumir, a integração postasse a mensagem no tópico resumido e marcasse esse tópico como o local para postar comentários adicionais do Discourse. Não resumiria comentários adicionais do Slack nesse tópico no Discourse; o objetivo seria redirecionar a conversa para o Discourse sobre esse tópico. Isso parece lógico para mim:

  • DADO: existe um local para armazenar o ID da mensagem do Slack associado a um tópico
  • E: novos comentários em um tópico são postados como comentários na mensagem do Slack armazenada
  • ENTÃO: defina o ID da mensagem do Slack para um tópico ao usar o recurso de integração do slackbot post thread, fazendo com que novos comentários do Discourse no tópico sejam anunciados nesse tópico, incluindo links de volta para o tópico/comentário do Discourse

Isso realmente ajudaria a disseminar o conceito de “consulte primeiro o Discourse antes de perguntar”.

5 curtidas

Tudo isso soa ótimo para mim!

:100:

3 curtidas

Como auxílio visual, isso parece com a UX do lado do Slack que você quer promover?

… oh meu, o ano foi removido do início da thread. alguma ideia?

@riking Um pouco, mas com algumas diferenças.

O anúncio não ficaria exatamente assim; ele seria postado pelo lado watch da integração. Não mencionaria que foi movido. Aqui está um exemplo da interface atual (sem threads), da integração com o Slack conforme implementei para makerforums:

No modelo com threads, a primeira dessas postagens iniciaria uma thread no Slack, e o comentário de Nedman estaria em uma resposta encadeada no Slack. Quando post thread :thread_url é usado, o :thread_url seria armazenado junto com o novo tópico, e o lado watch da integração de chat postaria a postagem inicial do tópico e todos os comentários subsequentes nessa thread do Slack, mas o conteúdo seria o mesmo.

A integração watch thread te leva para o Discourse, onde você precisa escrever o título e tem a oportunidade de editar a postagem inicial do tópico antes de publicá-la. Assim, o anúncio postado no Slack já creditará a pessoa que executou post thread como autor, seguido por uma linha com o título do tópico como texto do link, que leva ao Discourse, e depois uma citação destacada do início da postagem. A mudança que proponho aqui é que, com uma configuração não padrão e por canal (ou seja, uma opção watch, não uma configuração global do plugin de integração de chat do site), esse conteúdo seria postado na thread em vez de no canal. (Não “também enviar para o canal” — o que anularia o propósito da mudança para nós.) Comentários adicionais nesse novo tópico no Discourse também iriam para a mesma thread do Slack.

E, já que você pediu palpites, 2017, o ano em que o Slack lançou as threads?

2 curtidas

Tenho pensado sobre isso e li a documentação da API chat.postMessage do Slack, e acredito que posso resumir meu texto extenso em algo muito mais simples.

Apenas watch, e não follow, tem a capacidade de escolher respostas em threads, por meio de um mecanismo que ainda estou tentando determinar. Alternativamente, @david, o que você acha de um novo filtro de regra thread com precedência mute thread watch follow, e encaminhar essa regra até trigger_notification para habilitar comportamentos sensíveis à regra?

  1. Se watch estiver configurado para threads (ou, alternativamente, se uma regra thread for definida), ao enviar uma notificação de nova postagem para um canal do Slack, se o tópico da postagem tiver um ts do Slack associado a ele, poste nessa thread do Slack definindo thread_ts com o valor de ts fornecido pelo Slack.

  2. Ao enviar uma notificação de nova postagem para um canal do Slack, e o tópico da postagem não tiver um ts associado a ele, armazene o ts retornado na resposta para o tópico (para que futuras postagens sobre o tópico possam ser threadadas, caso watch esteja configurado para threads).

  3. Ao usar o comando post thread :thread_url, armazene o ts da thread no tópico criado, que será utilizado apenas por regras watch em threads.

Aqui estão meus pensamentos e preocupações atuais:

  1. Como determinar se deve postar em threads com base em cada regra. Um novo filtro parece ser a opção mais fácil para mim no momento, mas talvez eu esteja perdendo algo.

  2. O fluxo do URL original da postagem no Slack e do ID da thread através do fluxo de transcrição é o que mais me parece opaco atualmente. Parece que realmente preciso adicionar um ID de thread específico por provedor em algum lugar e preservá-lo até salvar a postagem. Eu implementaria isso apenas para o ts do Slack, mas presumivelmente não será a única integração de chat com threads.

  3. Para postagem, acho que preciso armazenar o ts do Slack em um campo personalizado específico do Slack no Tópico, e não em um campo de thread genérico DiscourseChat.

1 curtida

A variável booleana ‘threading’ realmente precisa ser por regra? Por que não criar uma nova configuração do site

chat_integration_slack_thread_responses

Se estiver habilitada e tivermos um registro do ID da thread do tópico, enviaremos as notificações subsequentes para a thread do Slack.

Sim, acho que está tudo bem. Basta usar um campo personalizado específico do Slack para o tópico. Se sentirmos a necessidade de implementar isso para outros provedores no futuro, podemos tornar a solução mais genérica.

Sim, isso é muito complicado. Como uma versão 1, eu tentaria incluir algo como

<!--SLACK_THREAD_ID=abcdefg-->

no topo da postagem. Então, o plugin pode verificar as postagens que começam com essa string e atribuir o campo personalizado. Não é perfeito, mas talvez seja um bom ponto de partida?

2 curtidas

Muito obrigado!

Ontem à noite, implementei e tenho testes passando em toda a pilha (embora ainda não tenha testado em produção) meus dois primeiros ACs, mas ainda não o fluxo de transcrição, usando um campo personalizado em Topic e uma regra thread. Então, estou fazendo bom progresso para conseguir mostrar código em pelo menos um PR de rascunho.

Também tenho um commit separado para remover o pstore_get não utilizado do provedor do Slack. Como esse é o único uso de pstore em toda a pilha, você gostaria que eu também removesse todos os pstore_* de app/initializers/discourse_chat.rb nesse commit de limpeza?

É exatamente onde eu comecei, e certamente teria sido mais fácil!

No entanto, pelo menos para o meu caso de uso (e já ouvi isso de pessoas em outras empresas, não somos únicos), diferentes canais têm preferências diferentes sobre se threads devem ser usadas. Existem canais que são destinados a serem usados com threads (porque a maioria das pessoas se importa apenas com alguns tópicos) e canais que são fortemente contra threads (porque threads escondem informações importantes).

Vi dois aspectos essencialmente não relacionados impulsionando essa preferência:

  • Membros: Canais com a maioria dos membros usando IRC ativamente há décadas estão acostumados a desambiguar mentalmente threads de conversas intercaladas em um único canal e não querem clicar em threads para ver conteúdo importante, enquanto canais com a maioria dos membros vindo do email esperam que as conversas sejam threadizadas e que se clique nas conversas que lhes interessam.
  • Propósito: Canais com finalidade de anúncio tendem a ser fortemente threadizados, mas canais com fins de pesquisa ou colaboração muitas vezes intencionalmente não são threadizados porque threads escondem informações a menos que você as note e clique nelas.

Se você quiser ter alguma sintaxe comum para opções de regra, eu pensaria que Rule poderia ser expandida de modo geral para ter um valor :options que, como :tags, seja um array. Suponho que faria sentido pegar uma página dos shells de linha de comando, de modo que /discourse [watch|follow|mute] -algo -aqui defina :options para ['algo', 'aqui'] — reservando um - inicial para introduzir uma opção. Então seria /discourse watch minha-categoria-slug #tagged-foo -threaded. Não sei quanto mais trabalho isso seria em comparação com o que já fiz. Você tem sentimentos fortes de um lado ou do outro aqui? Vejo argumentos para ambos os lados: adicionar outro valor a Rule torna mais complicado escrever um provedor de chat; adicionar outro valor de filtro torna outro recurso específico do Slack (como postar uma transcrição) que torna a interface mais complicada para usuários que não são do Slack. Claro que posso estar perdendo algo que tornaria mais difícil do que penso; por exemplo, se um slug de categoria pudesse começar com - e isso se tornaria ambíguo; o shell usa -- para significar “tudo após isso não é um argumento”, mas talvez pudéssemos inverter para -- significar “tudo após isso é uma opção.” Se você quiser que eu pesquise isso, por favor, me dê alguma direção sobre a sintaxe que você consideraria apropriada para especificar opções de regra. Mas apenas adicionar thread parece mais simples para mim, então, na ausência de uma direção específica para adicionar um recurso geral de “opções”, vou aguardar para fazer qualquer mudança nessa direção.

[Edição: Mudar de um filtro de regra para uma opção definitivamente complicaria a UI, que teria que crescer para suporte geral a opções gerais, e isso não parece uma ótima escolha para mim. Então, agora, tendo olhado para a UI, prefiro manter o filtro; acho que é mais limpo.]

Para o fluxo de transcrição de post, obrigado pela ideia do comentário HTML. Para o meu caso de uso, não vai me prejudicar de forma alguma; honestamente, espero ser o usuário principal, pelo menos inicialmente. Esse é um hack simples e legal.

Tenho uma ideia separada, não para embutir neste PR, de que seria bom ter um mapeamento do canal para a mensagem sendo postada até a categoria na qual o post resultante do Discourse deve ser feito. Para que isso aconteça, acho que a transcrição mudaria melhor para ter um envelope ou sidecar, momento em que o envelope ou sidecar poderia ter tanto a categoria quanto o ID do Slack. Isso parece uma quantidade substancial de aprendizado para mim, já que ainda estou na fase de “pesquisa avançada do problema” aprendendo Ruby on Rails. :wink:

2 curtidas

Outra ideia para aprimorar ainda mais esse recurso:

E se houvesse outra configuração, cross_post_to_channel_after_hours (padrão 48?) ou algo assim, onde, se o tempo desde a última resposta for maior que x horas, a postagem fosse enviada ao thread com a flag “enviar também para o canal”.

Não leve minha sugestão muito a sério agora, se você só quiser fazer as coisas funcionarem sem ela primeiro (provavelmente uma estratégia melhor!). Apenas para reflexão…

De forma alguma uma ideia maluca, mas não pretendo implementá-la, pois isso quebraria meu caso de uso principal e não tenho necessidade disso em nenhum outro lugar. :smiling_face: No entanto, entendo perfeitamente que outras pessoas gostariam de ter essa funcionalidade!

Se fosse uma configuração normal, em vez de uma opção por canal, seria chat_integration_slack_copy_threads_to_channel_after_hours, que teria como padrão 0 (não enviar), mas você pode definir qualquer valor. Conceitualmente é bastante simples, mas exige mais trabalho, pois é necessário buscar o tópico (usando o código inicialmente escrito para transcrições, e não tenho certeza se exigiria refatoração) para tomar uma decisão sobre definir uma flag simples.

Mas, se você quiser trabalhar nisso, espero que o que estou fazendo sirva como uma boa base. Apenas peço que não ative por padrão, pois se isso fosse ativado em uma atualização e meus usuários fossem “spamados” por eu curar conteúdo para o Discourse, eu teria usuários insatisfeitos.

1 curtida

Para simplificar as coisas, acho que você poderia apenas verificar a data da postagem anterior no tópico do Discourse.

(Isso se comportaria de forma um pouco diferente em alguns casos, mas poderia ser um bom ponto de partida)

@david Tenho um rascunho de PR que passa nos testes unitários conforme os escrevi. Ainda não tentei executá-lo em produção contra o Slack, então não gostaria de mesclá-lo até que isso seja feito. Mas, pelo menos, todos os testes unitários passam para mim, e tentei adicionar testes significativos para eles.

Também coloquei o comentário de ID no final em vez do início da postagem, pois parecia mais provável de sobreviver e menos propenso a ser distorcido ali, e tentei ser conservador ao analisá-lo.

Obrigado pelo seu trabalho neste plugin!

Corrigi minhas falhas iniciais de linting, mas agora testes que não alterei estão falhando. Estou baseado na versão mais recente do master, e os testes passam localmente. Você tem alguma informação sobre os testes que estão falhando?

4 curtidas

Limpei bastante o PR, mas ainda não está totalmente pronto. Tenho duas ou três coisas que estão me causando problemas até agora e ainda não sei como corrigi-las.

  1. Estou tentando usar fa-arrow-circle-o-right como ícone do tópico, e ele está aparecendo vazio na interface do meu site ao vivo. (Tenho executado su discourse -c 'bundle exec rake assets:precompile' && sv restart unicorn após fazer o checkout da minha branch no meu site ao vivo para testar no servidor.) Adicionei-o ao plugin.rb e também fiz referência a ele, então estou perdido sobre quais são os próximos passos. Existe uma lista de ícones do Font Awesome aprovados para uso no Discourse? Encontrei lib/svg_sprite/svg_sprite.rb e chevron-right parece ótimo para esse caso de uso.

  2. Os testes estão todos passando para mim localmente, mas no Travis estou recebendo erros consistentes que parecem não ter relação com minhas alterações e, naturalmente, isso é difícil de investigar ou analisar. 13 falhas com um 404 em vez de algum outro código esperado (por exemplo, 200) em spec/lib/discourse_chat/provider/slack/slack_command_controller_spec.rb Corrigido ao não fazer “cargo-coding” com isolate_namespace e agora conheço o rake routes.

Consegui publicar com sucesso:

Pode haver mais coisas para limpar, mas acho que isso funciona.

Após a mesclagem, atualizarei Discourse Chat Integration adequadamente.

2 curtidas

Continuo encontrando novas oportunidades para aprender aqui. Agora sei como executar yarn prettier; em seguida, vou aprender a atualizar os testes do front-end…

Erro: Falha na afirmação: Você deve usar set() para definir a propriedade `channel` (de <(unknown):ember3806>) para `< (unknown):ember3799>`.

Muito obrigado por todo o seu trabalho aqui @mcdanlj - isso agora foi mesclado:

4 curtidas

Agradeço muito pelas suas avaliações tão úteis! Atualizei o post oficial da wiki de integração, conforme prometido. Se preferir destacar as mudanças de outras formas, estou à vontade para isso; não tenho nenhum orgulho de autoria ou coisa assim. :smiling_face:

3 curtidas

Por favor, habilite o encadeamento nas Configurações de integração de chat para o Slack, como em:

Habilitar encadeamento de Posts para o Slack

Quer dizer que você deseja poder configurar o plug-in para se recusar a honrar a opção thread na integração?

Atualizamos para a versão atual 2.6 beta1a e os testes foram aprovados há alguns dias, mas, pelo que pude observar, nenhuma postagem do Slack com x-posts está sendo threadada desde a atualização. Ainda vemos postagens de tópico e respostas exibidas individualmente nos canais do Slack.