feat(like_post): add unlike support via remove.0 array dot-notation (v1.2.0)
Unlike is now implemented: add=\$empty, remove.0=STAR (verified via Network Interceptor). Adds optional mood parameter (default STAR). Removes the early-return error path for like=False. SPEC.md, CLAUDE.md, CHANGELOG.md updated; Unlike offene Punkte entry removed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,8 @@ Breaking changes (removed tools, changed parameters) increment the major version
|
|||||||
## [1.2.0] – 2026-04-17
|
## [1.2.0] – 2026-04-17
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
- **Unlike support** for `like_post`: passing `like=False` now removes a STAR reaction via
|
||||||
|
`add=$empty, remove.0=STAR` (array dot-notation). New optional `mood` parameter (default `"STAR"`).
|
||||||
- **Reminder write support** for `create_task` and `update_task`:
|
- **Reminder write support** for `create_task` and `update_task`:
|
||||||
- `reminder_unit`: `"MINUTE"`, `"HOUR"`, or `"DAY"`
|
- `reminder_unit`: `"MINUTE"`, `"HOUR"`, or `"DAY"`
|
||||||
- `reminder_value`: non-negative integer (e.g. `30` for "30 minutes before")
|
- `reminder_value`: non-negative integer (e.g. `30` for "30 minutes before")
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ Fehler bei falschen Parametern kommen nicht immer auf Top-Level:
|
|||||||
| `taskupdate2` | **⚠️ Encoding** | Recurrency flach top-level. Reminder **nur Dot-Notation** `reminder.*` — flache Keys, JSON-String, Brackets werden silent-ignored. |
|
| `taskupdate2` | **⚠️ Encoding** | Recurrency flach top-level. Reminder **nur Dot-Notation** `reminder.*` — flache Keys, JSON-String, Brackets werden silent-ignored. |
|
||||||
| `taskmark` | `taskId`, `complete` | `"true"`/`"false"` |
|
| `taskmark` | `taskId`, `complete` | `"true"`/`"false"` |
|
||||||
| `metadelete` | `id` | metaId des Tasks / Rezepts |
|
| `metadelete` | `id` | metaId des Tasks / Rezepts |
|
||||||
| `wallmood` | `wall_message_id`, `moodType` | `"STAR"` für Like |
|
| `wallmood` | `wall_message_id`, `add`, `remove`/`remove.0` | Like: `add="STAR", remove="$empty"`; Unlike: `add="$empty", remove.0="STAR"` (Array-Dot-Notation) |
|
||||||
| `taskcategoryput` | `name`, `emoji` | – |
|
| `taskcategoryput` | `name`, `emoji` | – |
|
||||||
| `taskcategorydelete` | `id` | metaId der Kategorie |
|
| `taskcategorydelete` | `id` | metaId der Kategorie |
|
||||||
| `taskcreatelist` | `name`, `taskListType`, `sharedToAll`, `color`, `emoji`, `scope` | `taskListType`: `SHOPPING_LIST`, `TODOS`, `OTHER`; `scope`: Kreis-metaId für nicht-primäre Kreise |
|
| `taskcreatelist` | `name`, `taskListType`, `sharedToAll`, `color`, `emoji`, `scope` | `taskListType`: `SHOPPING_LIST`, `TODOS`, `OTHER`; `scope`: Kreis-metaId für nicht-primäre Kreise |
|
||||||
@@ -158,9 +158,8 @@ Fehler bei falschen Parametern kommen nicht immer auf Top-Level:
|
|||||||
### Self-Like-Restriction
|
### Self-Like-Restriction
|
||||||
Eigene Posts können nicht geliked werden. API antwortet 200, macht aber nichts.
|
Eigene Posts können nicht geliked werden. API antwortet 200, macht aber nichts.
|
||||||
|
|
||||||
### Unlike nicht möglich
|
### Unlike
|
||||||
Service Worker verschlüsselt den Unlike-Request-Body.
|
Unlike via `remove.0=STAR` (Array-Dot-Notation). Verifiziert 2026-04-17 via Network-Interceptor.
|
||||||
Endpoint unbekannt. `like_post(like=False)` gibt Fehlermeldung zurück.
|
|
||||||
|
|
||||||
### mpstar / Rezept-Favorit
|
### mpstar / Rezept-Favorit
|
||||||
Service Worker fängt `mpstar` ab. `metamood` funktioniert nur auf
|
Service Worker fängt `mpstar` ab. `metamood` funktioniert nur auf
|
||||||
|
|||||||
@@ -275,26 +275,35 @@ POST https://api.familywall.com/api/metadelete
|
|||||||
a00.r.r → "true" (String)
|
a00.r.r → "true" (String)
|
||||||
```
|
```
|
||||||
|
|
||||||
### `wallmood` – Post liken
|
### `wallmood` – Post liken / unlike
|
||||||
POST https://api.familywall.com/api/wallmood
|
POST https://api.familywall.com/api/wallmood
|
||||||
|
|
||||||
**Body-Parameter:**
|
**Body-Parameter (Like):**
|
||||||
|
|
||||||
| Parameter | Wert |
|
| Parameter | Wert |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `wall_message_id` | Post-metaId ⚠️ nicht `wallId` oder `id`! |
|
| `wall_message_id` | Post-metaId ⚠️ nicht `wallId` oder `id`! |
|
||||||
| `moodType` | `"STAR"` für Like |
|
| `add` | `"STAR"` (Mood-Typ setzen) |
|
||||||
|
| `remove` | `"$empty"` (Sentinel für „nichts entfernen") |
|
||||||
|
|
||||||
|
**Body-Parameter (Unlike):**
|
||||||
|
|
||||||
|
| Parameter | Wert |
|
||||||
|
|---|---|
|
||||||
|
| `wall_message_id` | Post-metaId |
|
||||||
|
| `add` | `"$empty"` (Sentinel für „nichts hinzufügen") |
|
||||||
|
| `remove.0` | `"STAR"` (Array-Dot-Notation — `remove` ist ein Array) |
|
||||||
|
|
||||||
**Bekannte Einschränkungen:**
|
**Bekannte Einschränkungen:**
|
||||||
- Unlike: Endpoint/Parameter unbekannt (Service Worker verschlüsselt Request-Body)
|
|
||||||
- Self-Like: API antwortet 200, macht aber serverseitig nichts
|
- Self-Like: API antwortet 200, macht aber serverseitig nichts
|
||||||
- `moodType="NONE"` und andere Werte haben keine Wirkung
|
|
||||||
|
|
||||||
**Response:**
|
**Response:**
|
||||||
```
|
```
|
||||||
a00.r.r → Wall-Objekt mit moodMap, refAction: "MOOD_STAR"
|
a00.r.r → Wall-Objekt mit moodMap, refAction: "MOOD_STAR"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Verifiziert am:** 2026-04-17 via Network-Interceptor (echter Request-Body)
|
||||||
|
|
||||||
### `taskcategoryput` – Kategorie erstellen/aktualisieren
|
### `taskcategoryput` – Kategorie erstellen/aktualisieren
|
||||||
POST https://api.familywall.com/api/taskcategoryput
|
POST https://api.familywall.com/api/taskcategoryput
|
||||||
|
|
||||||
@@ -949,7 +958,6 @@ bevor er den Server erreicht. Die Transformation ist ohne Service-Worker-Analyse
|
|||||||
|
|
||||||
## Offene Punkte
|
## Offene Punkte
|
||||||
|
|
||||||
- Unlike-Endpoint (Service Worker blockiert Analyse)
|
|
||||||
- `mpstar` / `isFavorite` für Rezepte (Service Worker blockiert Analyse, siehe oben)
|
- `mpstar` / `isFavorite` für Rezepte (Service Worker blockiert Analyse, siehe oben)
|
||||||
- Erinnerungen (reminder) – nur Premium-Account
|
- Erinnerungen (reminder) – nur Premium-Account
|
||||||
- Wiederholungen (repeat) – nur Premium-Account
|
- Wiederholungen (repeat) – nur Premium-Account
|
||||||
|
|||||||
@@ -1901,42 +1901,32 @@ def delete_circle(circle_id: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
@mcp.tool()
|
@mcp.tool()
|
||||||
def like_post(post_id: str, like: bool = True) -> str:
|
def like_post(post_id: str, like: bool = True, mood: str = "STAR") -> str:
|
||||||
"""Like a wall post/activity with a STAR mood.
|
"""Like or unlike a wall post/activity.
|
||||||
|
|
||||||
IMPORTANT: Ask the user for confirmation before calling this tool.
|
IMPORTANT: Ask the user for confirmation before calling this tool.
|
||||||
|
|
||||||
Note: Unlike (like=False) is not yet supported. The Family Wall API offers
|
|
||||||
no discoverable endpoint or parameter to remove a like. Passing like=False
|
|
||||||
returns an error without making any API call.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
post_id: Wall post ID from get_activities (e.g. ``wall/23431854_31119189``).
|
post_id: Wall post ID from get_activities (e.g. ``wall/23431854_31119189``).
|
||||||
like: Must be ``True``. ``False`` is reserved for future unlike support.
|
like: ``True`` to add a like (default), ``False`` to remove it.
|
||||||
|
mood: Mood type to set or remove. Default is ``"STAR"``.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
JSON success indicator or an error message.
|
JSON with the resulting like state or an error message.
|
||||||
"""
|
"""
|
||||||
# Unlike is not yet supported: extensive FW_DEBUG=1 testing showed that
|
# Like: add=STAR, remove=$empty (idempotent set)
|
||||||
# wallmood with moodType="STAR" is an idempotent SET operation (not a toggle).
|
# Unlike: add=$empty, remove.0=STAR (array dot-notation, verified via Network Interceptor)
|
||||||
# Tested and ruled out: moodType variations ("NONE", "REMOVE", "DELETE", ""),
|
if like:
|
||||||
# moodStarShortcut parameter, and alternative endpoints (all return 502).
|
|
||||||
# See SPEC.md for full investigation notes.
|
|
||||||
if not like:
|
|
||||||
return json.dumps(
|
|
||||||
{"error": "Unlike is not yet supported. The unlike mechanism is unknown."},
|
|
||||||
ensure_ascii=False,
|
|
||||||
indent=2,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Verified via FW_DEBUG=1:
|
|
||||||
# - Parameter 'wall_message_id': post ID as returned by get_activities
|
|
||||||
# - Parameter 'moodType': "STAR" (Family Wall's internal like type; "LIKE" is silently
|
|
||||||
# mapped to "STAR" server-side — use "STAR" directly)
|
|
||||||
# - Response a00.r.r: full wall message object with moodMap showing resulting state
|
|
||||||
params: dict[str, Any] = {
|
params: dict[str, Any] = {
|
||||||
"wall_message_id": post_id,
|
"wall_message_id": post_id,
|
||||||
"moodType": "STAR",
|
"add": mood,
|
||||||
|
"remove": "$empty",
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
params = {
|
||||||
|
"wall_message_id": post_id,
|
||||||
|
"add": "$empty",
|
||||||
|
"remove.0": mood,
|
||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -1968,15 +1958,18 @@ def like_post(post_id: str, like: bool = True) -> str:
|
|||||||
|
|
||||||
result: dict[str, Any] = {"liked": now_liked, "id": post_id, "author": account_id}
|
result: dict[str, Any] = {"liked": now_liked, "id": post_id, "author": account_id}
|
||||||
|
|
||||||
# Surface a warning when the like call apparently had no effect, so the
|
if now_liked != like:
|
||||||
# caller can distinguish a successful like from a silent API rejection
|
if like:
|
||||||
# (e.g. rate limit, unsupported post type, or self-like restriction).
|
|
||||||
if not now_liked:
|
|
||||||
result["warning"] = (
|
result["warning"] = (
|
||||||
"Like may not have been applied. "
|
"Like may not have been applied. "
|
||||||
"Possible causes: rate limit, unsupported post type (e.g. FAMILY_CREATED), "
|
"Possible causes: rate limit, unsupported post type (e.g. FAMILY_CREATED), "
|
||||||
"or self-like restriction."
|
"or self-like restriction."
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
result["warning"] = (
|
||||||
|
"Unlike may not have been applied. "
|
||||||
|
"Possible causes: post was not liked, rate limit, or API restriction."
|
||||||
|
)
|
||||||
|
|
||||||
return json.dumps(result, ensure_ascii=False, indent=2)
|
return json.dumps(result, ensure_ascii=False, indent=2)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user