Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions fp-plugins/mastodon/developer-docs/00-Mental-Model.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ It maps FlatPress objects to Mastodon objects:

Media export has one additional compatibility rule that developers must keep in mind: one Mastodon status may carry multiple images, or exactly one audio/video attachment, but not a mixed audio/video/image set. The plugin therefore collects all local media for change detection and diagnostics, then selects one exportable media family per status before upload: images first, otherwise one audio item, otherwise one video item with its poster sent only as an upload thumbnail.

Status export has a similar budgeting rule: Mastodon counts each recognized URL as the instance's `characters_reserved_per_url` value, but sentence punctuation immediately after a link is normal text. Local text limiting therefore runs through `plugin_mastodon_status_text_url_spans()` before `plugin_mastodon_status_text_length()` and `plugin_mastodon_limit_status_text()` so a trailing comma or full stop cannot be hidden inside the URL placeholder budget.

```mermaid
flowchart LR
FP[FlatPress entries comments media tags]
Expand Down
4 changes: 3 additions & 1 deletion fp-plugins/mastodon/developer-docs/01-Process-Map.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ Remote import must respect local deletion protection. A remote reply with a tomb
flowchart TD
Dirty[Dirty entry or comment]
Parent{Reply target known?}
Text[Build Mastodon text with URL budget tags emoji]
Text[Build Mastodon text with URL spans budget tags emoji]
MediaPlan{Entry media plan}
Upload[POST api v2 media]
Poll[GET api v1 media id until ready]
Expand All @@ -256,6 +256,8 @@ flowchart TD
Update -- failure after upload --> Cleanup
```

URL-aware text budgeting runs before the media plan. `plugin_mastodon_status_text_url_spans()` extracts only the Mastodon-countable URL core, so punctuation after `https://...` such as commas and full stops remains in the normal text budget instead of being hidden in `characters_reserved_per_url`.

The media plan is one of the most important extension points. It compares attachment signatures and description signatures. If attachments did not change, the plugin can reuse remote media IDs. If only descriptions changed and the instance supports status `media_attributes` according to `api_versions[mastodon]` or the version fallback, it updates alt text without re-uploading. Otherwise it re-uploads.

Before the media plan computes signatures or uploads anything, it applies the Mastodon status media-family policy:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ This matrix links implementation functions to the process map. It is intentional
| plugin_mastodon_collect_local_entry_media | P7 | Extracts images/galleries/audio/video from FlatPress content. | FlatPress entry body and companion plugin formats | Builds candidate local media descriptors. | Local media extraction tests |
| plugin_mastodon_build_entry_status_text | P5 | Builds Mastodon text from FlatPress entry. | Entry title/body, tags, URL budget, instance limits | Adds permalink and hashtag footer. | Text/tag/URL tests |
| plugin_mastodon_build_comment_status_text | P6 | Builds Mastodon reply text from FlatPress comment. | Comment author/body, public comment URL | Localizes and converts text/emoji. | Comment export tests |
| plugin_mastodon_status_text_url_spans / plugin_mastodon_status_text_length / plugin_mastodon_limit_status_text | P5/P6 | Apply Mastodon-compatible URL placeholder budgeting before truncating status text. | Plain status text and `configuration.statuses.characters_reserved_per_url` | Treats trailing sentence punctuation as normal text so the server-side 500-character validator is not exceeded by URL-adjacent commas or full stops. | URL punctuation-budget regression tests |
| plugin_mastodon_import_remote_entry | P3/P8 | Writes a remote top-level status as FlatPress entry. | Remote status JSON | Writes entry, media, tags, mappings and the imported status source footer built from `Status.url`. | Remote entry import tests |
| plugin_mastodon_imported_status_footer_bbcode | P3 | Builds the imported Mastodon status source footer BBCode. | Mastodon `Status.url` | Emits `[url=... target=_blank rel="nofollow noopener noreferrer"]Mastodon[/url]` for the single toot/status. | Status-footer target tests |
| plugin_mastodon_import_remote_comment / plugin_mastodon_protect_missing_local_exported_comment_by_remote_id | P4/P8/P9 | Imports a remote reply only after enforcing local-deletion ownership. | Remote context descendant, `comments_remote`, targeted comment shard | Recreates a pending-delete tombstone for a missing `source=local` file and refuses stale import without loading all shards. | Partial-sync and bypass-hook tests |
Expand Down Expand Up @@ -52,7 +53,7 @@ flowchart TD
CommentReplyGate[Comment/reply synchronization gate]
CommentOptin[Visitor comment Mastodon opt-in]
State[State scheduler logging filesystem guards]
Text[Text URL tags emoji BBCode HTML conversion]
Text[Text URL spans budgets tags emoji BBCode HTML conversion]
Media[Media extraction validation upload import cleanup]
API[HTTP transport Mastodon API wrappers]
Sync[Import export deletion orchestrators]
Expand Down Expand Up @@ -92,6 +93,7 @@ flowchart TD
| OAuth scopes | `plugin_mastodon_oauth_scopes()`, discovery helpers | options `oauth_registered_scopes` | Scope discovery tests |
| Profile widget | `plugin_mastodon_widget()`, `plugin_mastodon_refresh_profile_cache_for_sync()`, `plugin_mastodon_refresh_profile_cache_from_account()` | `profile/profile.json`, local avatar file | Widget cache/render/sync tests |
| Text conversion | BBCode/HTML/text helper functions | usually no state | HTML/BBCode/URL/tag/emoji tests |
| URL-adjacent punctuation | `plugin_mastodon_status_text_url_spans()`, `plugin_mastodon_status_text_length()`, `plugin_mastodon_limit_status_text()` | None | URL punctuation-budget tests |

## Reading guidance

Expand Down
2 changes: 2 additions & 0 deletions fp-plugins/mastodon/developer-docs/04-API-Compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ The plugin reads `/api/v2/instance` with a short instance-information timeout an
| Video size limit | `configuration.media_attachments.video_size_limit` | No local size rejection when unknown. |
| Audio size limit | `configuration.media_attachments.audio_size_limit` | Falls back to video size if explicit audio limit is absent; otherwise no local rejection. |

For status text length, `configuration.statuses.characters_reserved_per_url` is applied only to the URL entity that Mastodon will parse. `plugin_mastodon_status_text_url_spans()` intentionally leaves trailing sentence punctuation such as `,` or `.` outside the URL span, so those characters remain part of the normal text budget and the local export limit matches Mastodon server validation more closely.

## Internal budgets and operational limits

| Name | Value | Purpose |
Expand Down
Loading