From 15dedb3d3fd83678944adb74df7572cf08fe0978 Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Stobbe Date: Mon, 31 Aug 2026 07:58:20 +0200 Subject: [PATCH] humhub: Umfragen anlegen und auflisten (poll-create / poll-list) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Die Polls-REST-API ist auf der Instanz aktiv, der Skill kannte sie nicht. Zwei Abweichungen vom Muster der Post-API, die beide in HTTP 500 'Internal error while save a poll!' enden: * Der Controller macht $poll->load(Yii::$app->request->post()) — die Felder gehoeren unter den Yii-Formnamen 'Poll', nicht unter 'data'. * Die Optionen heissen beim Anlegen 'newAnswers'; 'answers' ist die Leseform und wird beim POST ignoriert. Beim Lesen ist limit Pflicht: ohne Begrenzung antwortet die Instanz ab etwa 25 Umfragen ebenfalls mit 500. Quelle: humhub/polls, controllers/rest/PollsController.php + models/Poll.php. Verifiziert an Space inmedias (Umfrage 36). Co-Authored-By: Claude Opus 5 (1M context) --- README.md | 5 +- plugins/humhub/.claude-plugin/plugin.json | 4 +- plugins/humhub/skills/humhub/SKILL.md | 27 ++++++- .../humhub/__pycache__/humhub.cpython-312.pyc | Bin 0 -> 29299 bytes plugins/humhub/skills/humhub/humhub.py | 76 ++++++++++++++++++ 5 files changed, 105 insertions(+), 7 deletions(-) create mode 100644 plugins/humhub/skills/humhub/__pycache__/humhub.cpython-312.pyc diff --git a/README.md b/README.md index 9b53c6a..366d1fc 100644 --- a/README.md +++ b/README.md @@ -79,9 +79,10 @@ natürlicher klingen. Basiert auf Wikipedias „Signs of AI writing". ### humhub -HumHub (humhub.inmedias.it) über die REST-API: Wiki-Seiten und Posts auflisten, +HumHub (humhub.inmedias.it) über die REST-API: Wiki-Seiten, Posts und Umfragen auflisten, anzeigen, anlegen und aktualisieren — via mitgelieferter, self-contained -`humhub.py` (`wiki-list/get/update/create`, `post-list/create/update`). +`humhub.py` (`wiki-list/get/update/create`, `post-list/create/update`, +`poll-list/create`). - Voraussetzung: `HUMHUB_API_TOKEN` als Umgebungsvariable bzw. dotenv-Datei (kein Token im Plugin). Token nur als berechtigter Benutzer unter diff --git a/plugins/humhub/.claude-plugin/plugin.json b/plugins/humhub/.claude-plugin/plugin.json index 5ade752..ed8e959 100644 --- a/plugins/humhub/.claude-plugin/plugin.json +++ b/plugins/humhub/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "humhub", - "version": "0.1.0", - "description": "HumHub via REST-API: Wiki-Seiten und Posts auflisten, anzeigen, anlegen und aktualisieren (humhub.py).", + "version": "0.2.0", + "description": "HumHub via REST-API: Wiki-Seiten, Posts und Umfragen auflisten, anzeigen, anlegen und aktualisieren (humhub.py).", "author": { "name": "inmedias.it" } diff --git a/plugins/humhub/skills/humhub/SKILL.md b/plugins/humhub/skills/humhub/SKILL.md index b6ff490..7463e2d 100644 --- a/plugins/humhub/skills/humhub/SKILL.md +++ b/plugins/humhub/skills/humhub/SKILL.md @@ -1,13 +1,13 @@ --- name: humhub -description: HumHub Wiki-Seiten und Posts lesen/erstellen/aktualisieren via REST-API. Use when the user mentions "HumHub", "Space", "Wiki-Seite in HumHub" or "Post/Beitrag". -version: 0.1.0 +description: HumHub Wiki-Seiten, Posts und Umfragen lesen/erstellen/aktualisieren via REST-API. Use when the user mentions "HumHub", "Space", "Wiki-Seite in HumHub", "Post/Beitrag" or "Umfrage/Poll". +version: 0.2.0 --- # HumHub (humhub.py) Interagiert mit HumHub (https://humhub.inmedias.it) über die REST-API: -Wiki-Seiten und Posts auflisten, anzeigen, anlegen und aktualisieren — über die +Wiki-Seiten, Posts und Umfragen auflisten, anzeigen, anlegen und aktualisieren — über die mitgelieferte, self-contained `humhub.py`. ## Ausführen @@ -59,6 +59,27 @@ werden nicht committet). ./humhub.py post-update [datei|-] ``` +### Umfragen + +```bash +./humhub.py poll-list [--limit N] +./humhub.py poll-create "" --answers "A|B|C" \ + [--file beschreibung.md] [--anonymous] [--multiple] [--hide-results] +``` + +Antwortoptionen mit `|` trennen, mindestens zwei. Der Beschreibungstext kommt +wie überall aus einer Datei oder `-`; Markdown ist erlaubt. Ohne `--anonymous` +ist sichtbar, wer wie gestimmt hat — bei Anmeldungen mit begrenzten Plätzen ist +das der Sinn der Sache. + +Zwei Eigenheiten der Polls-API, die zu `HTTP 500 "Internal error while save a +poll!"` führen, wenn man dem Muster der Post-API folgt: die Felder gehören +unter den Yii-Formnamen **`Poll`** (nicht `data`), und die Optionen heißen beim +Anlegen **`newAnswers`** (beim Lesen `answers`). Beim Lesen ist `limit` Pflicht +und nicht Komfort — ohne Begrenzung antwortet die Instanz ab ~25 Umfragen +ebenfalls mit 500. Ein fehlgeschlagener POST legt nichts an; vor einem zweiten +Versuch trotzdem mit `poll-list` prüfen. + Inhalte (Markdown) aus Datei oder `-` (stdin) übergeben — nicht als langes Shell-Argument (Sonderzeichen). `container_id` akzeptiert eine numerische Container-ID, einen **Space-Slug** oder eine **Space-URL** (`resolve_container` diff --git a/plugins/humhub/skills/humhub/__pycache__/humhub.cpython-312.pyc b/plugins/humhub/skills/humhub/__pycache__/humhub.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f1dcaa94707df923ede1567a8a2c21237a878a0e GIT binary patch literal 29299 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 W9TSmzhN@3^%l8feFYwiD^8R1`%hjC# literal 0 HcmV?d00001 diff --git a/plugins/humhub/skills/humhub/humhub.py b/plugins/humhub/skills/humhub/humhub.py index 8219c79..03597ec 100755 --- a/plugins/humhub/skills/humhub/humhub.py +++ b/plugins/humhub/skills/humhub/humhub.py @@ -212,6 +212,61 @@ def cmd_post_create(args: argparse.Namespace) -> None: print(f"Topics: {', '.join(saved_topics)}") +def cmd_poll_list(args: argparse.Namespace) -> None: + session, _ = get_session() + container_id = resolve_container(session, args.container_id) + # limit ist Pflicht, nicht Komfort: ohne Begrenzung antwortet die Instanz + # bei vielen Umfragen mit HTTP 500 statt mit einer Liste. + data = api_get(session, f"/polls/container/{container_id}?limit={args.limit}") + results = data.get("results", []) + if not results: + print("(keine Umfragen)") + return + for poll in results: + antworten = [a.get("answer", "") for a in poll.get("answers", [])] + zu = " [geschlossen]" if poll.get("closed") else "" + print(f"ID {poll.get('id')}{zu}: {poll.get('question', '')}") + print(f" {' | '.join(antworten)}") + + +def cmd_poll_create(args: argparse.Namespace) -> None: + """Umfrage anlegen. + + Zwei Abweichungen von der Post-API, die beide mit HTTP 500 + ("Internal error while save a poll!") enden, wenn man sie übersieht: + + * Der Controller macht `$poll->load(Yii::$app->request->post())` — Yii + erwartet die Felder deshalb unter dem Formnamen **`Poll`**, nicht unter + `data` wie bei Posts und Wiki-Seiten. + * Die Optionen heißen beim Anlegen **`newAnswers`**; `answers` ist die + Leseform und wird beim POST ignoriert. + + Quelle: humhub/polls, controllers/rest/PollsController.php + models/Poll.php. + Pflicht sind `question` und mindestens zwei Antworten. + """ + session, _ = get_session() + container_id = resolve_container(session, args.container_id) + antworten = [a.strip() for a in args.answers.split("|") if a.strip()] + if len(antworten) < 2: + sys.exit("Error: mindestens zwei Antwortoptionen nötig " + "(--answers 'Ja|Nein').") + beschreibung = read_file(args.file) if args.file else "" + + payload = {"Poll": { + "question": args.question, + "description": beschreibung, + "newAnswers": antworten, + "anonymous": 1 if args.anonymous else 0, + "allow_multiple": 1 if args.multiple else 0, + "show_result_after_close": 1 if args.hide_results else 0, + "is_random": 0, + }} + data = api_post(session, f"/polls/container/{container_id}", payload) + print(f"Umfrage erstellt (ID {data.get('id')}): {data.get('question')}") + print("Optionen: " + " | ".join(a.get("answer", "") + for a in data.get("answers", []))) + + def cmd_post_update(args: argparse.Namespace) -> None: session, _ = get_session() message = read_file(args.file) @@ -412,6 +467,27 @@ def main() -> None: p.add_argument("--topics", default=None, help="Komma-getrennte Topic-Namen (ersetzt bestehende)") p.set_defaults(func=cmd_post_update) + # poll-list + p = sub.add_parser("poll-list", help="Umfragen eines Containers auflisten") + p.add_argument("container_id", help="Space-Slug, URL oder numerische Container-ID") + p.add_argument("--limit", type=int, default=10, help="Max. Anzahl (Standard: 10)") + p.set_defaults(func=cmd_poll_list) + + # poll-create + p = sub.add_parser("poll-create", help="Neue Umfrage anlegen") + p.add_argument("container_id", help="Space-Slug, URL oder numerische Container-ID") + p.add_argument("question", help="Die Frage (Pflicht)") + p.add_argument("--answers", required=True, + help="Antwortoptionen, mit | getrennt: 'Ja|Nein|Vielleicht' " + "(mindestens zwei)") + p.add_argument("--file", default=None, + help="Markdown-Datei mit dem Beschreibungstext, '-' für stdin") + p.add_argument("--anonymous", action="store_true", help="anonyme Abstimmung") + p.add_argument("--multiple", action="store_true", help="Mehrfachauswahl erlauben") + p.add_argument("--hide-results", action="store_true", + help="Ergebnis erst nach Ende der Umfrage zeigen") + p.set_defaults(func=cmd_poll_create) + args = parser.parse_args() args.func(args)