Compartilhe seus casos de uso de API REST do Discourse 🧑‍💻

Olá a todos :slight_smile:

Muitas pessoas usam a API do Discourse para diversos fins, desde tarefas automatizadas até interações com outros aplicativos.

Vocês podem compartilhar como a utilizam?

  • Para qual finalidade?

  • Que tecnologia/software/linguagem de programação vocês usam para isso?

Aqui estão algumas maneiras como eu a utilizo, para dar alguns exemplos:

  • Eu uso um webhook de item revisável que executa um script PHP, o qual utiliza a API do Discourse para acionar a exclusão automática de spammers. Com muitos posts sinalizados todos os dias em minha comunidade, e com uma precisão de detecção de spam de 100%, isso facilita o trabalho dos administradores e moderadores, pois eles não precisam mais revisar manualmente a maioria dessas contas (eu não recomendaria o uso desse método, pensei e testei cuidadosamente antes de usá-lo).

  • Uso um webhook do Ko-Fi (um site de doações) que utilizará a API do Discourse via script PHP para atualizar o valor de uma configuração de um componente de tema. O objetivo é ter uma barra de progresso de doações exibida no Discourse, que será atualizada em tempo real.

  • Eu a uso para fins de teste com o Insomnia. Pode ser para popular minha instância de teste com conteúdo específico, testar requisições ao pensar em projetos que gostaria de criar, ajudar pessoas no meta, etc.

E vocês? Sintam-se à vontade para serem exaustivos, tenho certeza de que há muitos usos interessantes para ouvir :slight_smile:


Tópico de referência sobre a API: Discourse REST API Documentation
Documentação oficial: https://docs.discourse.org/

8 curtidas

Eu gerencio um fórum para meteorologistas amadores (observadores do tempo). Eu e outra pessoa fornecemos um feed de dados meteorológicos que centenas de outras pessoas ao redor do mundo usam para gerar suas próprias previsões hiperlocais.

Um de nossos usuários escreveu alguns scripts estatísticos complexos para verificar a qualidade de sua previsão e também a disponibilidade dos feeds. Se seus scripts encontrarem dados ausentes, quebrados ou atrasados nos feeds, eles criam uma postagem na categoria do fórum que é usada para dar suporte ao software de previsão, permitindo que outros meteorologistas saibam que há um problema que também pode afetá-los.

Os scripts para detectar anomalias nos feeds usam PHP. Eles geram um arquivo JSON descrevendo o problema e, em seguida, usam cURL para fazer o upload da postagem através da API.

6 curtidas

Recentemente, experimentei muitas plataformas que permitem encadear etapas e compartilharei uma que me deixou animado: Reconhecimento Óptico de Caracteres para detectar texto em uma imagem e anexá-lo à postagem do Discourse!

Meu tópico de sandbox mostra como funciona: https://notes.maiki.interi.org/t/testing-ocr-calls/403

Fiz o primeiro no Pipedream e explicarei como fiz, seguindo as etapas. Há um recurso beta para compartilhar fluxos de trabalho nesse serviço, e o seguinte é compartilhado em https://pipedream.com/new?h=tch_3Z6fa9.

:information_source: Embora isso possa ser um guia aprofundado sobre o uso do Pipedream com o Discourse, vou manter os detalhes leves, pois já saí dessa plataforma e compartilharei mais sobre isso mais tarde. :slight_smile:

Etapas

O esboço geral é: enviar o URL da imagem para a API Google Cloud Vision, executar os resultados pelo ChatGPT e, em seguida, anexar os resultados à postagem no Discourse.

Gatilho

Screenshot 2023-08-08 at 11-23-21 OCR Test - Pipedream

Isso fornece um webhook para enviar dados. No Discourse, criei um webhook com duas configurações específicas:

Screenshot 2023-08-08 at 11-24-41 Admin - notes

O disparo apenas em Eventos de Postagem significa que meu tópico inicial não acionará o processo; isso é útil para mim, pois posso planejar usar tópicos como contêineres para aplicar funções externas (eu as chamo de “notas funcionais”).

O disparo apenas nessa tag significa que posso usar tags para controlar quais webhooks são produzidos por tópico; geralmente, eu teria apenas uma tag “funções”, para manter a lógica do processo simples.
O webhook envia uma carga útil com muitas informações, e usaremos os IDs do tópico e da postagem mais tarde no processo.

Fim baseado em condição

Esta é uma etapa para verificar se um motivo de edição está incluído. Se estiver, ele interrompe o fluxo de trabalho.
Na última etapa, atualizo a postagem e incluo um Motivo de Edição, e essa verificação garante que eu não continue atualizando a postagem:sweat_smile:

:information_source: Uma das razões pelas quais parei de usar o Pipedream foi porque minhas verificações de webhook estavam consumindo créditos no serviço. Não acho que deveria pagar para processar condicionalmente um webhook, daí a mudança…

Extrair o URL da imagem

Decidi que, para este teste, cada postagem teria uma única imagem carregada nela. Esta etapa verifica o valor “cooked” e usa a seguinte expressão regular para capturar o URL:

/https?:\/\/[^\s"]+/

Chamada da API Google Cloud Vision

Esta é uma etapa de código personalizada no Pipedream. Os componentes pré-fabricados não faziam o que eu queria, e o serviço também tem um assistente de código que pode escrever código a partir de um prompt; como essas chamadas de API são diretas, foi fácil produzi-las com esse método.

Ele pega o valor da etapa anterior ({{steps.extract_by_regular_expression.$return_value[0].match}}), e este é o código:

import { axios } from "@pipedream/platform";

export default defineComponent({
  props: {
    imageUrl: {
      type: "string",
      label: "Image URL",
      description: "URL of the image to be processed by Google Vision API",
    },
    apiKey: {
      type: "string",
      label: "API Key",
      description: "Your Google Cloud API Key",
      secret: true,
    },
  },
  async run() {
    const url = `https://vision.googleapis.com/v1/images:annotate?key=${this.apiKey}`;
    const body = {
      requests: [
        {
          image: {
            source: {
              imageUri: this.imageUrl,
            },
          },
          features: [
            {
              type: "TEXT_DETECTION",
            },
          ],
        },
      ],
    };

    const config = {
      method: "POST",
      url,
      data: body,
    };

    const response = await axios(this, config);
    return response;
  },
});

ChatGPT para edição

Pega a saída da etapa anterior ({{steps.google_cloud.$return_value.responses[0].fullTextAnnotation.text}}) e a passa como mensagem do Usuário. Para a mensagem do sistema, tenho:

Você está lendo a saída de uma API de visão que detectou texto em uma imagem. Revise a mensagem e edite-a para clareza. Retorne apenas o texto editado sem comentários.

Anexar à postagem no Discourse

Outra seção de código personalizada, pois as ações pré-fabricadas do Discourse no Pipedream cobrem apenas alguns cenários (criar um tópico ou uma postagem), e eu quero anexar o texto à postagem.

Primeiro, aqui está o código:

import { axios } from "@pipedream/platform";

export default defineComponent({
  props: {
    discourse: {
      type: "app",
      app: "discourse",
    },
    postId: {
      type: "string",
      label: "Post ID",
      description: "The ID of the post to append text to",
    },
    text: {
      type: "string",
      label: "Text",
      description: "The text to append to the post",
    },
    editReason: {
      type: "string",
      label: "Edit Reason",
      description: "The reason for editing the post",
      optional: true,
    },
  },
  async run({ steps, $ }) {
    const url = `https://${this.discourse.$auth.domain}/posts/${this.postId}.json`;
    const response = await axios($, {
      method: "GET",
      url: url,
      headers: {
        "Api-Username": `${this.discourse.$auth.api_username}`,
        "Api-Key": `${this.discourse.$auth.api_key}`,
      },
    });

    const updatedText = `${response.raw} ${this.text}`;

    return await axios($, {
      method: "PUT",
      url: url,
      headers: {
        "Api-Username": `${this.discourse.$auth.api_username}`,
        "Api-Key": `${this.discourse.$auth.api_key}`,
      },
      data: {
        post: {
          raw: updatedText,
          edit_reason: this.editReason,
        },
      },
    });
  },
});

Essas propriedades para a etapa são preenchidas assim:

ID da Postagem

Captura o ID da postagem da carga útil original: {{steps.trigger.event.body.post.id}}
Isso é usado para editar essa postagem diretamente.

Texto
---

<blockquote>
 {{steps.chat.$return_value.generated_message.content}}
</blockquote>

[details="Texto detectado"]
{{steps.google_cloud.$return_value.responses[0].textAnnotations[0].description}}
[/details]

Basicamente, quero adicionar uma linha horizontal abaixo de cada imagem, com uma citação de texto editado e os detalhes para verificar a saída bruta.
Como cada postagem terá uma imagem, isso funciona muito facilmente. Pergunto-me como fazer isso com várias imagens ao mesmo tempo? :thinking:

Motivo da Edição

Detecção de Texto OCR

Isso é adicionado como o motivo da edição para a atualização da postagem, o que evitará um loop de atualização da postagem devido à etapa no início. :point_up: :recycle: :ng:

:information_source: Acho super útil incluir sempre um motivo de edição, especialmente ao lidar com serviços externos.


E é isso! Como você pode ver no meu sandbox, funciona muito bem!

Tenho uma viagem chegando e planejo refinar a edição da OpenAI para também traduzir para o inglês, se necessário, essa é uma opção que eu teria adicionado ao prompt do sistema para este fluxo de trabalho.

2 curtidas