humhub: Direktnachrichten senden (mail-send)
Die REST-API kann das Mail-Modul, das Skill bisher nicht — Direktnachrichten mussten von Hand in der Weboberflaeche geschrieben werden. Der Stolperstein ist die Empfaengeraufloesung: Profil-Slug und Benutzername sind nicht dasselbe (zu /u/serge/ gehoert "Serge"), und get-by-username unterscheidet Gross-/Kleinschreibung. resolve_user() nimmt deshalb ID, Benutzername oder Profil-URL und faellt auf einen Durchlauf der Benutzerliste zurueck, der beides case-insensitive vergleicht. Kein Befehl zum Lesen von Konversationen: fremde Nachrichten gehoeren nicht ungefragt in einen Modellkontext. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
4a20da2ed2
commit
e00395fc64
2 files changed
+81
No files matched your search
@@ -91,6 +91,25 @@ Beide nehmen wie `fetch` eine **Content-ID** oder Perma-URL (nicht die Post-/
|
|||||||
Wiki-Seiten-ID) und lösen das Zielobjekt selbst auf — funktioniert für Posts
|
Wiki-Seiten-ID) und lösen das Zielobjekt selbst auf — funktioniert für Posts
|
||||||
und Wiki-Seiten.
|
und Wiki-Seiten.
|
||||||
|
|
||||||
|
### Direktnachrichten
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./humhub.py mail-send <empfaenger> "<betreff>" [datei|-]
|
||||||
|
./humhub.py mail-send https://humhub.inmedias.it/u/serge/ "Betreff" entwurf.md
|
||||||
|
./humhub.py mail-send jan.stobbe,26 "Betreff" -
|
||||||
|
```
|
||||||
|
|
||||||
|
Empfänger sind Benutzername, Profil-URL oder numerische ID; mehrere mit Komma.
|
||||||
|
|
||||||
|
**Slug ≠ Benutzername.** Zur Profil-URL `/u/serge/` gehört der Benutzername
|
||||||
|
`Serge`, und `get-by-username` unterscheidet Groß-/Kleinschreibung. Wer den
|
||||||
|
Slug einsetzt, bekommt sonst `User not found!`. `mail-send` fängt das ab: erst
|
||||||
|
`get-by-username`, dann ein Durchlauf der Benutzerliste, der Benutzername und
|
||||||
|
Slug ohne Rücksicht auf Groß-/Kleinschreibung vergleicht.
|
||||||
|
|
||||||
|
Zum Lesen von Konversationen gibt es bewusst keinen Befehl — Nachrichten
|
||||||
|
anderer gehören nicht ungefragt in einen Modellkontext.
|
||||||
|
|
||||||
Inhalte (Markdown) aus Datei oder `-` (stdin) übergeben — nicht als langes
|
Inhalte (Markdown) aus Datei oder `-` (stdin) übergeben — nicht als langes
|
||||||
Shell-Argument (Sonderzeichen). `container_id` akzeptiert eine numerische
|
Shell-Argument (Sonderzeichen). `container_id` akzeptiert eine numerische
|
||||||
Container-ID, einen **Space-Slug** oder eine **Space-URL** (`resolve_container`
|
Container-ID, einen **Space-Slug** oder eine **Space-URL** (`resolve_container`
|
||||||
|
|||||||
@@ -348,6 +348,61 @@ def cmd_comment_create(args: argparse.Namespace) -> None:
|
|||||||
print(f"Perma: https://humhub.inmedias.it/content/perma?id={content_id}")
|
print(f"Perma: https://humhub.inmedias.it/content/perma?id={content_id}")
|
||||||
|
|
||||||
|
|
||||||
|
# ── Mail (Direktnachrichten) ─────────────────────────────────────────────────
|
||||||
|
|
||||||
|
def resolve_user(session: requests.Session, value: str) -> int:
|
||||||
|
"""Resolve a user ID, username, or profile URL (…/u/<slug>/) to a user ID.
|
||||||
|
|
||||||
|
Slug und Benutzername sind nicht dasselbe: zu https://…/u/serge/ gehört der
|
||||||
|
Benutzername "Serge". `get-by-username` kennt nur den Benutzernamen und
|
||||||
|
unterscheidet Groß-/Kleinschreibung — deshalb der Fallback über die
|
||||||
|
Benutzerliste, der auch den Slug vergleicht.
|
||||||
|
"""
|
||||||
|
value = value.strip()
|
||||||
|
if value.isdigit():
|
||||||
|
return int(value)
|
||||||
|
name = value
|
||||||
|
if "/" in value:
|
||||||
|
teile = [t for t in urlparse(value).path.split("/") if t]
|
||||||
|
if teile:
|
||||||
|
name = teile[-1]
|
||||||
|
|
||||||
|
r = session.get(f"{BASE_URL}/user/get-by-username",
|
||||||
|
params={"username": name})
|
||||||
|
if r.ok:
|
||||||
|
return int(r.json()["id"])
|
||||||
|
|
||||||
|
page = 1
|
||||||
|
while True:
|
||||||
|
data = api_get(session, f"/user?limit=50&page={page}")
|
||||||
|
results = data.get("results", [])
|
||||||
|
for u in results:
|
||||||
|
username = (u.get("account") or {}).get("username", "")
|
||||||
|
slug_teile = [t for t in urlparse(u.get("url", "")).path.split("/") if t]
|
||||||
|
slug = slug_teile[-1] if slug_teile else ""
|
||||||
|
if name.lower() in (username.lower(), slug.lower()):
|
||||||
|
return int(u["id"])
|
||||||
|
if len(results) < 50:
|
||||||
|
break
|
||||||
|
page += 1
|
||||||
|
sys.exit(f"Error: Benutzer {value!r} nicht gefunden")
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_mail_send(args: argparse.Namespace) -> None:
|
||||||
|
session, _ = get_session()
|
||||||
|
ids = [resolve_user(session, teil) for teil in args.to.split(",") if teil.strip()]
|
||||||
|
if not ids:
|
||||||
|
sys.exit("Error: kein Empfänger angegeben")
|
||||||
|
message = read_file(args.file)
|
||||||
|
data = api_post(session, "/mail", {
|
||||||
|
"title": args.title,
|
||||||
|
"message": message,
|
||||||
|
"recipient": ids,
|
||||||
|
})
|
||||||
|
empfaenger = ", ".join(str(i) for i in ids)
|
||||||
|
print(f"Nachricht gesendet (Konversation {data.get('id')}) an Benutzer {empfaenger}")
|
||||||
|
|
||||||
|
|
||||||
# ── Fetch (perma-/content-id-agnostisch) ─────────────────────────────────────
|
# ── Fetch (perma-/content-id-agnostisch) ─────────────────────────────────────
|
||||||
|
|
||||||
def parse_content_ref(ref: str) -> int:
|
def parse_content_ref(ref: str) -> int:
|
||||||
@@ -513,6 +568,13 @@ def main() -> None:
|
|||||||
p.add_argument("file", help="Markdown-Datei oder '-' für stdin")
|
p.add_argument("file", help="Markdown-Datei oder '-' für stdin")
|
||||||
p.set_defaults(func=cmd_comment_create)
|
p.set_defaults(func=cmd_comment_create)
|
||||||
|
|
||||||
|
# mail-send
|
||||||
|
p = sub.add_parser("mail-send", help="Direktnachricht an Benutzer senden")
|
||||||
|
p.add_argument("to", help="Benutzername, Profil-URL oder ID; mehrere mit Komma")
|
||||||
|
p.add_argument("title", help="Betreff")
|
||||||
|
p.add_argument("file", help="Markdown-Datei oder '-' für stdin")
|
||||||
|
p.set_defaults(func=cmd_mail_send)
|
||||||
|
|
||||||
# post-update
|
# post-update
|
||||||
p = sub.add_parser("post-update", help="Post aktualisieren")
|
p = sub.add_parser("post-update", help="Post aktualisieren")
|
||||||
p.add_argument("id", type=int, help="Post-ID")
|
p.add_argument("id", type=int, help="Post-ID")
|
||||||
|
|||||||
Reference in new issue
Block a user