Federate podcast episodes from both Jetpack podcast features - #3575
Open
pfefferle wants to merge 7 commits into
Open
Federate podcast episodes from both Jetpack podcast features#3575pfefferle wants to merge 7 commits into
pfefferle wants to merge 7 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Adds support in the Jetpack integration to federate Jetpack “podcast episode” posts by emitting an ActivityPub attachment for the episode’s audio enclosure (and cover art), similar to existing podcast integrations.
Changes:
- Hook
activitypub_attachmentsinActivitypub\Integration\Jetpackand derive audio/cover-art data from Jetpack’sEpisode_Block_Tags::get_block_attrs(), enriching existing core-enclosure attachments when present. - Add PHPUnit coverage for the new attachment behavior, including a small mock of Jetpack’s
Episode_Block_Tags. - Add a changelog entry for the new federation capability.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
integration/class-jetpack.php |
Adds activitypub_attachments filter handler to emit/enrich podcast episode audio + cover art attachments. |
tests/phpunit/tests/integration/class-test-jetpack.php |
Adds integration tests for the new Jetpack podcast attachment behavior and mock setup. |
tests/phpunit/data/mocks/class-episode-block-tags.php |
Introduces a minimal mock for Episode_Block_Tags::get_block_attrs() used by tests. |
.github/changelog/add-jetpack-podcast-attachment |
Documents the new Jetpack podcast episode federation behavior. |
Jetpack's podcast-episode block stores the audio URL, mime type and cover art as block attributes, read via Episode_Block_Tags::get_block_attrs(). Hook the activitypub_attachments filter from the Jetpack integration to add the episode audio (and cover art) as an ActivityPub attachment, read directly from the block rather than relying on WordPress core's asynchronous enclosure meta. When the enclosure path already added the same audio, enrich it with the cover art instead of duplicating. Claude-Session: https://claude.ai/code/session_01Eam1mCnfuFmXKSAtYFxaua
pfefferle
force-pushed
the
add/jetpack-podcast-attachment
branch
from
July 23, 2026 10:58
fdfccfb to
61bd75b
Compare
- esc_url_raw() can drop an unsafe media URL to an empty string; return early so no attachment is added without a url. Adds a regression test. - Remove the activitypub_attachments filter in the Jetpack test tear_down so it cannot leak into later tests. Claude-Session: https://claude.ai/code/session_01Eam1mCnfuFmXKSAtYFxaua
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Proposed changes:
Jetpack has two podcast features, built at the same time by different people, and an episode can come from either one:
jetpack/podcast-episodeblock carrying the audio URL, mime type and cover art.The first version of this PR only handled the block, and I had it labelled as Jetpack Podcast, which is the other one. Thanks to Rob for catching that. It now covers both.
Neither surface reaches ActivityPub on its own. Episode audio is usually hosted off-site, so it has no attachment ID, and
Transformer\Base::filter_unique_attachments()drops every media entry without one, so that audio never survives to theactivitypub_attachmentsfilter. The integration resolves the episode itself and either adds the audio, or replaces the artwork when the media library already contributed the file.activitypub_attachmentsrather than adding a transformer subclass. A subclass is winner-take-all, so a site running Podlove or Seriously Simple Podcasting alongside a Jetpack podcast would get one behavior instead of both.normalize_url(), so a site that moved to HTTPS after publishing does not federate the same file twice.mediaTypewhen the block has no mime type, rather than sending an empty string that stops receivers classifying the attachment at all.I also pulled the max-attachments resolution out of
Transformer\PostintoActivitypub\get_max_attachments(), since the integration needs the same value and I did not want a second copy of the meta, option and filter precedence.Known gap
Podlove_Podcast_PublisherandSeriously_Simple_Podcastingoverrideget_attachment()and never applyactivitypub_attachments, so on a site running either of those this callback does not fire. I left that alone here, but it means the three podcast integrations sit at three different levels for one problem.Worth a follow-up
filter_unique_attachments()drops media without anid, butPost::get_enclosures()deliberately builds complete entries for enclosures that are not in the media library, andBase::transform_attachment()opens with a passthrough for id-less entries that is unreachable today. Fixing that one place would let every site with an external enclosure federate it, and would remove most of the workaround here. It changes shared behavior for every post that merely links an audio file though, and there is no enclosure test coverage yet, so I think it should be its own PR.Other information:
Testing instructions:
Posts to Podcast:
jetpack/podcast-episodeblock.attachmentholds the audio withtype: Audio, the rightmediaType, and the episode cover art asicon.httpand the otherhttps.Jetpack Podcast:
icon.Changelog entry
Included in the branch (
.github/changelog/add-podcast-episode-attachments).