Comparte tus casos de uso de la API REST de Discourse 🧑‍💻

Hola a todos :slight_smile:

Mucha gente utiliza la API de Discourse para diversos fines, desde tareas automatizadas hasta interacciones con otras aplicaciones.

¿Podéis compartir cómo la utilizáis?

  • ¿Con qué fin?

  • ¿Qué tecnología/software/lenguaje de programación utilizáis para este asunto?

Aquí os muestro cómo la utilizo para dar algunos ejemplos:

  • Utilizo un webhook de elementos revisables que ejecuta un script PHP, el cual utiliza la API de Discourse para activar la eliminación automática de spammers. Con muchas publicaciones marcadas cada día en mi comunidad, y con una precisión de detección de spam del 100%, facilita el trabajo de los administradores y moderadores, ya que ya no tienen que revisar manualmente la mayoría de estas cuentas (no recomendaría usar este método, lo pensé y probé cuidadosamente antes de usarlo).

  • Utilizo un webhook de Ko-Fi (un sitio web de donaciones) que utilizará la API de Discourse a través de un script PHP para actualizar el valor de configuración de un componente temático. El objetivo es tener una barra de progreso de donaciones que se muestre en Discourse y que se actualice en tiempo real.

  • La utilizo para fines de prueba con Insomnia. Puede ser para poblar mi instancia de prueba con contenido específico, probar solicitudes al pensar en proyectos que me gustaría crear, ayudar a la gente en meta, etc.

¿Y vosotros? Sentíos libres de ser exhaustivos, estoy seguro de que hay muchos usos interesantes de los que oír hablar :slight_smile:


Tema de referencia sobre la API: Discourse REST API Documentation
Documentación oficial: https://docs.discourse.org/

8 Me gusta

Dirijo un foro para meteorólogos aficionados (observadores del tiempo). Yo y otra persona proporcionamos una fuente de datos meteorológicos que cientos de personas en todo el mundo utilizan para generar sus propias previsiones hiperlocales.

Uno de nuestros usuarios ha escrito unos complejos scripts estadísticos para comprobar la calidad de su previsión y también la disponibilidad de las fuentes. Si sus scripts encuentran datos faltantes, rotos o retrasados en las fuentes, crean una publicación en la categoría del foro que se utiliza para dar soporte al software de previsión, lo que permite a los demás pronosticadores saber que hay un problema que también podría afectarles.

Los scripts para detectar anomalías en las fuentes utilizan PHP. Generan un archivo JSON que describe el problema y luego utilizan cURL para subir la publicación a través de la API.

6 Me gusta

Experimenté mucho recientemente con varias plataformas que permiten encadenar pasos, y compartiré una que me entusiasmó: Reconocimiento Óptico de Caracteres para detectar texto en una imagen y agregarlo a la publicación de Discourse.

Mi tema de prueba muestra cómo funciona: https://notes.maiki.interi.org/t/testing-ocr-calls/403

Hice el primero en Pipedream y explicaré cómo lo hice siguiendo los pasos. Hay una función beta para compartir flujos de trabajo en ese servicio, y lo siguiente se comparte en https://pipedream.com/new?h=tch_3Z6fa9.

:information_source: Si bien esto sería una guía detallada para usar Pipedream con Discourse, seré breve en los detalles, ya que ya he dejado esa plataforma y compartiré más sobre eso más adelante. :slight_smile:

Pasos

El esquema general es: enviar la URL de la imagen a la API de Google Cloud Vision, procesar los resultados a través de ChatGPT y luego agregar los resultados a la publicación en Discourse.

Disparador

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

Esto proporciona un webhook para enviar datos. En Discourse creé un webhook con dos configuraciones específicas:

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

Solo se activa en Eventos de Publicación significa que mi tema inicial no activará el proceso; esto es útil para mí, ya que puedo planificar usar temas como contenedores para aplicar funciones externas (las llamo “notas funcionales”).

Solo se activa en esa etiqueta significa que puedo usar etiquetas para controlar qué webhooks se producen por tema; en general, solo tendría una etiqueta de “funciones” para mantener la lógica del proceso simple.

El webhook envía una carga útil con mucha información, y usaremos los IDs del tema y la publicación más adelante en el proceso.

Fin basado en condición

Este es un paso para verificar si se incluye una razón de edición. Si es así, detiene el flujo de trabajo.

En el último paso actualizo la publicación e incluyo una Razón de Edición, y esta verificación asegura que no siga actualizando la publicación:sweat_smile:

:information_source: Una de las razones por las que dejé de usar Pipedream fue porque mis verificaciones de webhook consumían créditos en el servicio. No creo que deba pagar para procesar condicionalmente un webhook, por lo tanto, sigo adelante…

Extraer la URL de la imagen

Decidí que para esta prueba cada publicación tendría una sola imagen cargada. Este paso verifica el valor “cocinado” y utiliza la siguiente expresión regular para obtener la URL:

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

Llamada a la API de Google Cloud Vision

Este es un paso de código personalizado en Pipedream. Los componentes prefabricados no hacían lo que quería, y el servicio también tiene un asistente de código que puede escribir código a partir de una indicación; como estas llamadas a la API son sencillas, fue fácil producirlas de esta manera.

Toma el valor del paso anterior ({{steps.extract_by_regular_expression.$return_value[0].match}}), y este es el 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 editar

Toma la salida del paso anterior ({{steps.google_cloud.$return_value.responses[0].fullTextAnnotation.text}}) y la pasa como mensaje del usuario. Para el mensaje del sistema tengo:

Eres el lector de la salida de una API de visión que detectó texto en una imagen. Revisa el mensaje y edítalo para mayor claridad. Devuelve solo el texto editado sin comentarios.

Agregar a la publicación en Discourse

Otra sección de código personalizado, ya que las acciones de Discourse prefabricadas en Pipedream solo cubren un par de escenarios (crear un tema o una publicación), y quiero agregar el texto a la publicación.

Primero, aquí está el 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,
        },
      },
    });
  },
});

Esas propiedades para el paso se completan de la siguiente manera:

ID de publicación

Obtiene el ID de la publicación de la carga útil original: {{steps.trigger.event.body.post.id}}

Esto se usa para editar esa publicación directamente.

Texto
---

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

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

Básicamente, quiero agregar una regla horizontal debajo de cada imagen, con una cita de texto editado y los detalles para verificar la salida sin procesar.

Dado que cada publicación tendrá una imagen, esto funciona muy fácilmente. Me pregunto cómo hacerlo con varias imágenes a la vez. :thinking:

Razón de edición

Detección de texto OCR

Esto se agrega como la razón de edición para la actualización de la publicación, lo que evitará un bucle de actualización de publicación debido al paso al principio. :point_up: :recycle: :ng:

:information_source: Me resulta muy útil incluir siempre una razón de edición, especialmente cuando se trata de servicios externos.


¡Y eso es todo! Como puedes ver en mi sandbox, ¡funciona bastante bien!

Tengo un viaje próximamente y planeo ajustar la edición de OpenAI para que también traduzca al inglés si es necesario, esa es una opción que habría agregado a la indicación del sistema para este flujo de trabajo.

2 Me gusta