Giantpaper.org

Author: giantpaper

  • “Content is King? I was wrong about it”

    “Content is King? I was wrong about it”

    Other than AI content dominating the Internet, and loads and loads of tracking everywhere, I like where the Internet is now. I like that web tech evolved enough so we could do cool stuff on websites. But I also miss personal sites & blogs. 😩

  • Ultimate Penguin Question

    I’ve never been able to study for hours. 🫤

  • Giantpaper on the Fediverse: Back and Better than Ever!

    Giantpaper on the Fediverse: Back and Better than Ever!

    Ever since the Great Federating of Giantpaper, I’ve been thinking about how I would get Activitypub to correctly display the different types of blog posts I have set up. Ex: this post, which looked like this on Mastodon:

    Or this one, which turned into this:

    There were some things I learned about WP posts ending up on the Fediverse through this plugin:

    • Custom fields (like those generated by Advanced Custom Fields) don’t get included, so links from my linklog posts won’t appear (which is why this post was posted as a micropost instead of a linkpost)
    • Most HTML gets stripped out by some Fedi services like Mastodon, which is why videos weren’t appearing on microposts

    The Activitypub plugin has a setting for tweaking the template that gets used for federation:

    …but there’s no template tag for custom fields (and no way to not have the plugin render video URLs as video embeds).

    Enter Filters

    I saw that there was a PR for making the post template filterable, that was upcoming for v2.0.0. And against my judgement, I jumped at it when it released, thinking there would be some sort of documentation for the new filters, but NOPE. I didn’t even know what the filter was called!! 😬 I did see the addition of a new filter name in v2.0.0.0, which is what I thought it was going to be, but actually trying to use it to filter stuff got me the dreaded “Your author URL does not return valid JSON for application/activity+json. Please check if your hosting supports alternate Accept headers.” error in WordPress’s Site Health page. And also I (somehow) found that outputting the contents of $template from the first parameter that it was actually meant to alter the post template (from the screenshot above with the [ap_....] tags), but I’m trying to figure out how to modify the HTML output of [ap_content]. So that wasn’t it.

    I saw that the plugin repo has a discussion board! And that people actually use said discussion board! I searched “filters” and found “Modifying ActivityPub posts via WordPress filter? #228“. Trying to add a filter for activitypub_post got me an error. So that wasn’t it either.

    (FYI, the filter name wasn’t what I was looking for, but I did find a Very Important Piece of info in the linked thread that helped me debug my code later. More on that later.)

    AND THEN, the search bar at the top, I searched for apply_filters (because if there’s a new way to filter content, it for sure would be added to the code via apply_filters()):

    searching for apply_filters() on Github automattic/wordpress-activitypub

    And there it was: Line 623 in includes/transformer/class-post.php:

    Screenshot showing activitypub_the_content being applied

    After some trial and error, I fiiiiiiiinally got it to work. 😩

    screenshot showing Now or Never by Audiomachine on Mastodon

    Behind the Scenes!

    Here is my (very unofficial) documentation for this:

    /**
     *
     * @param string  $content The outputted HTML of [ap_content]
     * @param WP_Post $post    The post object -- see https://developer.wordpress.org/reference/classes/wp_post/ and https://developer.wordpress.org/reference/functions/get_post/ for more info
     *
     */
    add_filter('activitypub_the_content', function($content, $post){
    
      // add code here
    
      return $content
    
    }, 100, 2);

    First the videos…

    This is just some normal non-WP specific code. So if you’re already familiar with PHP, you might already know this. But to make sure your videos show up in your fediposts:

      // Remove iframes from Youtube videos
      $content = preg_replace(
        "#<figure[^>]+><div[^>]+><iframe.+ src=\"https://www\.youtube\.com/embed/(.+)\?[^\"]+\".+></iframe></div></figure>#",
        "<p><a href=\"https://youtube.com/watch?v=\\1\">https://youtube.com/watch?v=\\1</a></p>",
        $content
      );
      // Remove iframes from Vimeo videos
      $content = preg_replace(
        "#<figure[^>]+><div[^>]+><iframe.+ src=\"https://player\.vimeo.com/video/(.+)\?[^\"]+\".+></iframe></div></figure>#",
        "<p><a href=\"https://vimeo.com/\\1\">https://vimeo.com/\\1</a></p>",
        $content
      );

    You’re basically removing the iframes and surrounding <figure> and <div> tags from around the videos and reformatting the embed URLs (inside the src="" attribute) back to their web accessible URLs (so https://www.youtube.com/embed/t476sB13EOghttps://www.youtube.com/watch?v=t476sB13EOg). And then linking to themselves, which will make Mastodon (and maybe other fediservers) think “oh hey, this is a link, let’s put up a preview”, and embeds the video.

    So from this:

    <figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper"><iframe loading="lazy" title="The Prince of Peace" width="500" height="375" src="https://www.youtube.com/embed/AQZqaz10TOM?feature=oembed" frameborder="0" allow="web-share" allowfullscreen></iframe></div></figure>

    To this:

    <p><a href="https://youtube.com/watch?v=AQZqaz10TOM">https://youtube.com/watch?v=AQZqaz10TOM</a></p>

    And the links!

    This uses some more WP-specific PHP to detect what post you’re displaying, but here’s what I have:

    // Linklog -- prepend external link to post
    $href = get_field('external_url', $post->ID);
    if (has_category('linklog', $post)) {
      $content = '<p><a href="' .$href. '">' .$href. '</a></p>' . $content;
    }

    All together now:

    add_filter('activitypub_the_content', function($content, $post){
    	// Remove iframes from Youtube videos
    	$content = preg_replace(
    		"#<figure[^>]+><div[^>]+><iframe.+ src=\"https://www\.youtube\.com/embed/(.+)\?[^\"]+\".+></iframe></div></figure>#",
    		"<p><a href=\"https://youtube.com/watch?v=\\1\">https://youtube.com/watch?v=\\1</a></p>",
    		$content
    	);
    	// Remove iframes from Vimeo videos
    	$content = preg_replace(
    		"#<figure[^>]+><div[^>]+><iframe.+ src=\"https://player\.vimeo.com/video/(.+)\?[^\"]+\".+></iframe></div></figure>#",
    		"<p><a href=\"https://vimeo.com/\\1\">https://vimeo.com/\\1</a></p>",
    		$content
    	);
    
    	// Linklog -- prepend external link to post
    	$href = get_field('external_url', $post->ID);
    	if (has_category('linklog', $post)) {
    		$content = '<p><a href="' .$href. '">' .$href. '</a></p>' .$content;
    	}
    	return $content;
    }, 100, 2);

    Edit

    Updated code to handle syntax highlighting better (it looks REEEALLY bad on Mastodon).

    Edit #2

    Mastodon does not apply monospace fonts to <pre>. TIL

    Edit #3

    Fixed syntax error in the last code snippet. Getting PHP and Javascript mixed up.