Erstelle benutzerdefinierte Automatisierungen

:information_source: Dies ist ein Entwurf und erfordert möglicherweise zusätzliche Arbeit.

Vokabular

  • trigger: Repräsentiert den Namen des Triggers, z. B. user_added_to_group
  • triggerable: Repräsentiert die Code-Logik, die mit einem Trigger verbunden ist, z. B. triggers/user_added_to_group_.rb
  • script: Repräsentiert den Namen des Skripts, z. B. send_pms
  • scriptable: Repräsentiert die Code-Logik, die mit einem Skript verbunden ist, z. B. scripts/send_pms.rb

Plugin API

add_automation_scriptable(name, &block)
add_automation_triggerable(name, &block)

Scriptable API

field

field :name, component: ermöglicht es Ihnen, einen anpassbaren Wert in der Benutzeroberfläche Ihrer Automatisierung hinzuzufügen.

Liste der gültigen Komponenten:

# foo muss eindeutig sein und repräsentiert den Namen Ihres Feldes.

field :foo, component: :text # generiert eine Texteingabe
field :foo, component: :list # generiert eine Mehrfachauswahl-Texteingabe, in die Benutzer Werte eingeben können
field :foo, component: :choices, extra: { content: [ {id: 1, name: 'your.own.i18n.key.path' } ] } # generiert eine Kombinationsfeld mit benutzerdefinierten Inhalten
field :foo, component: :boolean # generiert eine Kontrollkästchen-Eingabe
field :foo, component: :category # generiert einen Kategorie-Wähler
field :foo, component: :group # generiert einen Gruppen-Wähler
field :foo, component: :date_time # generiert einen Datums-/Zeit-Auswähler
field :foo, component: :tags # generiert einen Tag-Wähler
field :foo, component: :user  # generiert einen Benutzer-Wähler
field :foo, component: :pms  # ermöglicht die Erstellung einer oder mehrerer PM-Vorlagen
field :foo, component: :categories  # ermöglicht die Auswahl von null oder mehr Kategorien
field :foo, component: :key-value  # ermöglicht die Erstellung von Schlüssel-Wert-Paaren
field :foo, component: :message  # ermöglicht die Erstellung einer PM mit ersetzbaren Variablen
field :foo, component: :trustlevel  # ermöglicht die Auswahl einer oder mehrerer Vertrauensstufen
triggerables und triggerable!
# Definiert die Liste der für ein Skript zulässigen Triggerables
triggerables %i[recurring]

# Erzwingt einen Triggerable für Ihr Skript und ermöglicht auch die Erzwingung eines bestimmten Zustands für Felder
field :recurring, component: :boolean
triggerable! :recurring, state: { foo: false }
placeholders
# Markiert einen Schlüssel als ersetzbar in Texten unter Verwendung der Platzhaltersyntax `%%sender%%`
placeholder :sender

Beachten Sie, dass es in der Verantwortung des Skripts liegt, Werte für Platzhalter bereitzustellen und die Ersetzung mit input = utils.apply_placeholders(input, { sender: 'bob' }) durchzuführen.

script

Dies ist das Herzstück einer Automatisierung und wo die gesamte Logik stattfindet.

# context wird gesendet, wenn die Automatisierung ausgelöst wird, und kann sich zwischen Triggern stark unterscheiden
script do |context, fields, automation|
end

Lokalisierung

Jedes Feld, das Sie verwenden, hängt von i18n-Schlüsseln ab und wird nach ihrem Trigger/Skript benannt.

Zum Beispiel ein Skriptable mit diesem Inhalt:

field :post_created_edited, component: :category

Erfordert die folgenden Schlüssel in client.en.yml:

en:
  js:
    discourse_automation:
      scriptables:
        post_created_edited:
          fields:
            restricted_category:
              label: Category
              description: Optional, allows to limit trigger execution to this category

Beachten Sie, dass die Beschreibung hier optional ist.


Dieses Dokument wird versioniert – schlagen Sie Änderungen auf github vor.

7 „Gefällt mir“

Als ich sah, dass dies ein neues Thema war, wurde ich aufgeregt: Ich dachte, es wären mehr Details geteilt worden! :laughing:

Als jemand, der nicht in Ruby programmiert, aber sehr an Workflow-Automatisierung interessiert ist, hoffte ich, ich könnte durch Beispiele ein wenig mehr verstehen

:thinking:

Ich schätze, ich muss bei Developing Discourse Plugins - Part 1 - Create a basic plugin anfangen… :sweat_smile:

8 „Gefällt mir“

Ich habe diesen Abschnitt im Grunde aus dem Plugin-Thema herausgeschnitten, damit es nicht so aussieht, als ob Sie ihn kennen müssten, um die vorhandenen nutzen zu können. :slight_smile:

Ich stimme zu, dass es großartig wäre, wenn dies eine Schritt-für-Schritt-Anleitung wäre. Ich habe einen Hilferuf an die Community gesendet, um zu sehen, ob jemand Erfahrungen damit hat: :crossed_fingers:

5 „Gefällt mir“

Ein „Hallo Welt“-Beispiel wäre cool.
Wo sollten die Skripte gespeichert werden? Ich würde gerne ein wenig damit experimentieren.

4 „Gefällt mir“

Ich denke, Sie können benutzerdefinierte Skripte mit Chat GPT zusammen mit diesem Plugin schreiben.

Wahrscheinlich ist der beste Ort, um nachzusehen, das Automatisierungsskript, das dem Data Explorer-Plugin hinzugefügt wird: discourse-data-explorer/plugin.rb at main · discourse/discourse-data-explorer · GitHub. Es lohnt sich auch, die vorhandenen Skripte und Trigger des Automation-Plugins zu betrachten: https://github.com/discourse/discourse-automation/tree/main/lib/discourse_automation

Da es auf Meta nicht viele Informationen über das Hinzufügen benutzerdefinierter Automatisierungen gibt, hier ist eine Beispiel-plugin.rb-Datei, die ein Skript zum Aktualisieren der E-Mail-Einstellung für die Aktivitätszusammenfassung eines Benutzers hinzufügt. Das Skript kann durch die Trigger ‘user_added_to_group’ oder ‘user_removed_from_group’ des Automation-Plugins ausgelöst werden.

# frozen_string_literal: true

# name: automation-script-example
# about: Ein Beispiel, wie man ein Skript zu einer Automatisierung hinzufügt
# version: 0.0.1
# authors: scossar

enabled_site_setting :automation_script_example_enabled

after_initialize do
  reloadable_patch do
    if defined?(DiscourseAutomation)
      DiscourseAutomation::Scriptable::USER_UPDATE_SUMMARY_EMAIL_OPTIONS =
        "user_update_summary_email_options"
      add_automation_scriptable(
        DiscourseAutomation::Scriptable::USER_UPDATE_SUMMARY_EMAIL_OPTIONS
      ) do

        field :email_digests, component: :boolean

        version 1
        triggerables [:user_added_to_group, :user_removed_from_group]

        script do |context, fields, automation|
          if automation.script == "user_update_summary_email_options" && (context["kind"] == "user_added_to_group" || context["kind"] == "user_removed_from_group")
            user_id = context["user"].id
            digest_option = fields.dig("email_digests", "value")
            user_option = UserOption.find_by(user_id: user_id)

            if (user_option)
              user_option.update(email_digests: digest_option)
            end
          end
        end
      end
    end
  end
end

Der vollständige Plugin-Code ist hier: GitHub - scossar/automation-script-example: An example of how to add a custom script to the Discourse Automation plugin..

:warning: Bitte verwenden Sie diesen Code nicht unverändert auf einer Produktionsseite. Ich habe mir den Automatisierungscode erst heute Abend angesehen. Wenn ich Feedback zu möglichen Problemen mit dem Code erhalte, werde ich diesen Beitrag und das GitHub-Repository aktualisieren.

Bearbeitung: Meine Sorge war, wie man am besten mit dem Fall umgeht, dass mehrere Automatisierungsskripte durch die Trigger ‘user_added_to_group’ oder ‘user_removed_from_group’ ausgelöst werden. Die ursprüngliche Version des Plugins prüfte auf:

fields.has_key?("email_digests")

aber das erschien etwas unzuverlässig. Was wäre, wenn ein anderes Skript hinzugefügt würde, das ebenfalls einen email_digests-Schlüssel hätte?

Der aktualisierte Code übergibt den Parameter automation an den Codeblock und prüft:

automation.script == "user_update_summary_email_options"

Das sollte sicherstellen, dass das Skript nicht für die falsche Automatisierung ausgeführt wird.
… wenn ich noch einmal darüber nachdenke, ist es unwahrscheinlich, dass das Skript durch eine Automatisierung ausgelöst werden könnte, für die es nicht konfiguriert wurde :slight_smile:

7 „Gefällt mir“

Das würde ich auch gerne wissen – sobald man ein Repository wie das von @simon erstellt hat, wie wird es dann vom Plugin aufgerufen?

Muss man das gesamte Plugin forken und es zu den vorhandenen in https://github.com/discourse/discourse-automation/tree/main/lib/discourse_automation/scripts hinzufügen? Oder gibt es einen eleganteren Weg?

1 „Gefällt mir“

Sie müssen es wie jedes andere Discourse-Plugin installieren: Plugins in Discourse installieren. Sie würden also das Automatisierungs-Plugin installieren und Ihr Plugin installieren, das die benutzerdefinierten Skripte hinzufügt. Der Grund, warum es funktioniert, liegt in den hier definierten Methoden: https://github.com/discourse/discourse-automation/blob/main/lib/plugin/instance.rb. Im obigen Beispielcode sehen Sie, dass das benutzerdefinierte Skript mit einem Aufruf von add_automation_scriptable hinzugefügt wird.

Hinweis: Installieren Sie nicht die Beispielautomatisierung aus meinem GitHub-Repo, sondern nehmen Sie sie als Beispiel, wie das Automatisierungs-Plugin erweitert werden kann. (Ich habe vergessen, dass ich hier darauf verwiesen habe, und es aktualisiert, sodass es nur mit meiner geforkten Version des Discourse-Automatisierungs-Plugins funktioniert. Der Code, auf den ich hier verwiesen habe, ist jedoch immer noch gültig: Create custom Automations - #6 by simon. Ich werde das Plugin automation-script-example so schnell wie möglich aktualisieren, damit es ohne die Änderungen funktioniert, die ich an meiner geforkten Version des Automatisierungs-Plugins vorgenommen habe.)

Meine Sorge war unbegründet. Diese Bedingung ist nicht notwendig:

if automation.script == "user_update_summary_email_options" && (context["kind"] == "user_added_to_group" || context["kind"] == "user_removed_from_group")

Ich werde das Beispiel bald aktualisieren.

4 „Gefällt mir“

Liege ich richtig in der Annahme, dass benutzerdefinierte Automatisierungen eine selbst gehostete Installation (oder anderweitig direkten Backend-Zugriff auf das Dateisystem, auf dem Discourse installiert ist) erfordern?

2 „Gefällt mir“

Ja, wir sind jedoch sehr offen dafür, neue Automatisierungsskripte in das Community-Build zu integrieren. Was möchtest du bauen?

6 „Gefällt mir“

Speziell suchen wir nach einer Möglichkeit, bestimmte Zeichenfolgen in Beiträgen zu ersetzen (uns ist die genaue Syntax nicht wichtig, aber so etwas wie der Klartext @ref `Random.rand!` ) durch einen formatierten Link wie Random.rand!. Das Nachschlagen der genauen URL ist ein komplizierter Prozess mit Zehntausenden von möglichen Zielen, der mit Regexes (wie Auto linkify words/watched words) völlig undurchführbar ist und in einer Turing-vollständigen Plugin-ähnlichen Umgebung viel einfacher ist… daher war ich neugierig, ob Automatisierungen dies tun könnten.

Daher suchte ich nach einer Aktion nach der Bearbeitung, ähnlich dem, was der @system-Benutzer tut, wenn Sie den gesamten vorherigen Beitrag zitieren (siehe hier). Es wäre ein “Beitrag bearbeiten”-Skript, das bei “Beitrag erstellt” (oder vielleicht nach dem Kochen des Beitrags) ausgelöst wird… aber ich nehme an, dass das Automatisierungs-Framework keine solch allgemeine “Beitrag bearbeiten”-Aktion zulassen würde. Ich denke, es müsste eine ziemlich spezifische benutzerdefinierte Automatisierung für Links zu Julia-Dokumenten sein, was in einem Community-Build sicherlich keinen Sinn ergibt.

Ich könnte hier mit benutzerdefinierten Automatisierungen auf dem falschen Weg sein; ich habe nur erkundet, was möglich ist. Natürlich denken mutige Benutzer, als Forum für Programmiersprachen-Enthusiasten, bereits über die Programmierung von Bots nach, die die Discourse-API nutzen könnten, um dies zu tun.

1 „Gefällt mir“

Ich bin mir nicht sicher, ob Automatisierung das ist, was Sie hier suchen, da etwas, das hier kritisch erscheint, die „Endbenutzer“-Erfahrung ist. Mit Automatisierung würde dies nur nachträglich ersetzt werden.

Wenn ich über diese Art von Problem nachdenke, würde ich wahrscheinlich empfehlen, entweder ein benutzerdefiniertes Plugin oder eine Theme-Komponente zu verwenden.
Eine Theme-Komponente könnte wie folgt funktionieren:

  1. Der Benutzer tippt: ^Rand
  2. Ein HTTP-Aufruf an einen von Ihnen gehosteten Backend-Dienst wird getätigt, der alle Optionen mit URLs auflistet.
  3. Der Benutzer wählt die gewünschte Option aus und drückt Enter.
  4. Markdown wird zu [Random.rand!](https://docs.julialang.org/en/v1/stdlib/Random/#Random.rand!) geändert.

Ein Plugin, das die Markdown-Pipeline ergänzt, könnte ähnlich wie Onebox funktionieren und einfach beim Tippen automatisch verlinken, wobei die ursprüngliche Syntax beibehalten wird. z. B. ^Random.rand

Ich verstehe, dass Linkify nicht ideal ist, die Entdeckung ist schwierig, außerdem müssen Sie möglicherweise eine Website hosten, damit Sie sie zu lookup.docs.julialang.org?q=Random.rand! normalisieren.

Sicherlich ein sehr interessantes Problem. Ich denke, die Benutzererfahrung einer Theme-Komponente kann hier angemessen sein.

2 „Gefällt mir“

Das ist sehr großartig, danke für die Gedanken und Hinweise hier! Ich werde dies zu einem separaten Thema machen, wenn ich weitere Fragen (oder Antworten :slight_smile: ) habe.

2 „Gefällt mir“

Ich denke, ein benutzerdefiniertes Plugin, das bei einer Beitragsänderung ausgelöst wird, ist das, was Sie erstellen möchten. Ich vermute, dass es für Ihren Anwendungsfall, der einen einfachen Auslöser hat, einfacher ist, ein Plugin zu schreiben, als sich mit dem Automatisierungsplugin zu beschäftigen.

1 „Gefällt mir“

@McUles und @nathank, haben Sie die gesuchten Informationen gefunden?

Damit die benutzerdefinierte Automatisierung funktioniert, musste ich die folgenden Dateien ändern:

Benutzerdefiniertes Automatisierungsskript erstellt

Aktualisiert: server.en.yml

Benutzerdefinierter Automatisierungsname, Titel und Beschreibung im Abschnitt „scriptables“ der YML-Datei hinzugefügt.

Aktualisiert: client.en.yml

Benutzerdefinierter Automatisierungsname in „scriptables“ hinzugefügt; das Schlüsselwort „field“ hinzugefügt; innerhalb des Schlüsselworts „field“ „field_name“ gefolgt von „label“ und „description“ hinzugefügt.

Aktualisiert: scripts.rb

Benutzerdefinierter Automatisierungsname zur Liste der Skripte hinzugefügt. Beispiel: DATEINAME = „dateiname“

Aktualisiert: plugin.rb

Innerhalb von „after_initialize do“ den Pfad zum benutzerdefinierten Automatisierungsskript hinzugefügt. Beispiel: „lib/discourse_automation/scripts/dateiname“

Ich verstehe nicht ganz, was Sie dort geschrieben haben – handelt es sich um Änderungen am Automations-Plugin oder um wichtige Komponenten eines Schwester-Plugins, das die benutzerdefinierten Automatisierungen enthält?

Es wäre großartig, wenn dies in die OP eingearbeitet würde.

2 „Gefällt mir“

Das ist es. Ich kannte die Antwort auf Ihre Frage nicht wirklich, also hier ist, wie ich eine Antwort gefunden habe und auch die Antwort auf „Gibt es irgendwo ein Beispiel, das ich sehen könnte?“

Holen Sie sich zuerst dies: GitHub - discourse/all-the-plugins

Dann verwenden Sie grep für etwas wie „add_automation_scriptable“ und dann können Sie herausfinden, was es verwendet.

 (main) pfaffman@noreno:~/src/discourse-repos/all-the-plugins/official$ grep -r add_automation_scriptable
discourse-assign/plugin.rb:    add_automation_scriptable("random_assign") do
discourse-chat-integration/plugin.rb:    add_automation_scriptable("send_slack_message") do
discourse-chat-integration/plugin.rb:    add_automation_scriptable("send_chat_integration_message") do
discourse-data-explorer/plugin.rb:      add_automation_scriptable("recurring_data_explorer_result_pm") do
discourse-data-explorer/plugin.rb:      add_automation_scriptable("recurring_data_explorer_result_topic") do

Schauen Sie sich also vielleicht discourse-assign oder data-explorer an.

2 „Gefällt mir“