Month: August 2024

  • Marginally Better Shortlinks

    I’ve found myself tinkering with WordPress stuff a lot lately. Here’s another quick change I made for nicer shortlinks with a shorter domain that I have.

    This was inspired by trawling through jwz’ archives and hacks. This post in particular.

    The first piece of this puzzle is adding this location block to the nginx configs for bhh.sh. There’s probably a better way to do this to handle more types or remove the extra redirect.

    location ~* /p/(.*) {
      return 302 https://benharri.org?p=$1;
    }

    The other half is filtering the shortlink on the WordPress end. I’ve added this to the functions.php of my theme. Basic logic here is based on jwz’ base64 shortlinks, just minus the base64 and dumping the post ID right in there.

    add_filter( 'pre_get_shortlink', 'bhhsh_shortlink', 10, 4 );
    
    function bhhsh_shortlink( $shortlink, $id, $context, $allow_slugs ) {
      if ($context == 'query' && !is_singular())
        return false;
    
      $post = get_post( $id );
      if ( empty( $post ) )
        return false;
      $id = $post->ID;
      if ( empty( $id ) )
        return false;
    
      return 'https://bhh.sh/p/' . $id;
    }
  • WordPress IndieWeb setup with a block theme

    I’ve been tinkering around with IndieWeb integration on this site and wanted to document some notes getting all this running with a block theme.

    Theme

    I’m running a mildly customized version of Pulitzer. I’ve used the Create Block Theme plugin to export my changes and have published it as a standalone child theme here.

    Changes are mainly typography and header/footer changes. I’ve raised the font sizes across the board and switched to using system fonts to avoid shipping font files. Modern Font Stacks is lovely and I found this tiny plugin to pull all the families in to the font library.

    I’ve also started extending Pulitzer’s existing block bindings. I’m testing this as a stand-in for Syndication Links:

    Block Binding Callbacks

    https://tildegit.org/ben/putz-theme/src/commit/44fff0096816d959b588b53541bbd3762b4e9fab/functions.php#L426

    function putz_block_binding_callback_syndication_links
        ( array $source_args, WP_Block $block_instance, string $attribute_name ) {
      $post_id = $block_instance->context['postId'] ?? get_the_ID();
      $links = get_post_meta( $post_id, 'mf2_syndication', true);
      if ( empty( $links ) ) {
        return false;
      } else {
        return 'Also on: ' . implode( ' ', array_map( function($link) {
          $domain = wp_parse_url( $link, PHP_URL_HOST );
          return "<a href=\"$link\">$domain</a>";
        }, $links ) );
      }
    }

    Plugins

    Relevant Plugins
    PluginVersion
    IndieAuthVersion 4.5.2 by IndieWeb WordPress Outreach Club
    IndieBlocksVersion 0.13.0 by Jan Boddez
    IndieWebVersion 4.0.5 by IndieWebCamp WordPress Outreach Club
    MF2 FeedVersion 3.1.1 by IndieWeb WordPress Outreach Club
    MicropubVersion 2.4.0 by IndieWeb WordPress Outreach Club
    Syndication LinksVersion 4.4.20 by David Shanske
    WebmentionVersion 5.3.3 by Matthias Pfefferle
    WebSubVersion 3.2.1 by PubSubHubbub Team

    IndieBlocks

    I’m using IndieBlocks to provide microformats markup throughout my site. I’m also using the Note and Like post types. I’ve decided to keep those out of my main blog feed. Here’s the configs.

    The Syndication Links plugin handles publishing the actual syndication posts, and I use the hidden links for the markup. The clickable links are currently displayed with a block binding.

    IndieAuth

    This requires essentially no configuration, but I did find a nasty bug in the plugin code and helped debug a bit. Logging in with IndieAuth was hanging indefinitely, getting killed by php-fpm, and throwing a 504 timeout. I’m not super familiar with the code but this is the PR that fixed it.

    Shoutout to dshanske for helping me figure this one out and releasing a new plugin version with the fix!

    Bridgy

    I’m using both Bridgy and Bridgy Fed. I’m currently trying out POSSE for my mastodon and bluesky posts with Bridgy and publishing them as Notes here on this site. These are the publish targets I use via Syndication Links:

    My solution for keeping Notes and Likes out of my main blog feed was making sure to show them in my author feed in the IndieBlocks settings and adding a rel=feed link to my author page in the header.

    add_action( 'wp_head', function() { ?>
    <link rel="feed" type="text/mf2+html" href="https://benharri.org/author/ben/" />
    <?php } );

    The other solution I tried for this was using MF2 Feed and including them as rel=alternate but Bridgy doesn’t support mf2+json feeds yet. There’s an open issue to add support for this use case.

    One remaining thing that I haven’t figured out yet is pulling the syndication links out of the logs into the proper post meta. Still haven’t narrowed this down fully but it works perfectly fine when publishing with a Micropub client like Quill or IndiePass, so it feels like something to do with the block editor.

    My workaround is wp-cli + jq and feels entirely unsatisfying. Hoping to get that figured out soon.

  • Block themes are cool, actually

    WordPress block themes have grown on me.

    Spent a couple hours this weekend sprucing up tcpinball.org. Found this lovely block theme and it all came together quite nicely.

    Had a strange bug where the Navigation block stopped working on certain pages. Didn’t find the actual cause but it fixed itself when I disabled the Gutenberg plugin.

  • DNSSEC wasn’t worth it

    In reply to Calling Time on DNSSEC? by Geoff Huston.

    [… we] estimate that DNSSEC validation is performed around 1% of the time, given the DNS query profile of today’s data

    I run my own authoritative nameservers and have had a slight nagging feeling that I should’ve enabled DNSSEC years ago. It’s been on my perpetual to-do list but I’ve never gotten around to it. I’ve definitely caused some outages trying to get DNSSEC to work.

    Came across this article and it confirms that my procrastination was pretty OK in this specific case.

  • Internet Archeology

    Stumbled upon a silly blog I made for one of the German classes I took in undergrad.

    The account it was under used my long-dead @nmu.edu email so I ended up having to contact support to get back into it.

    Also found the final project page.

    I imported the posts and pages to this site just for archival sake without any of the bother ads on wp.com.

    At least I got my main username back from this discovery!

    The imported posts are here if you’re so inclined.

  • Matchplay Posting

    I post the results from the pinball tournaments I run on our site, which usually involves copying a previous post and updating all the info by hand. I took some time this week to put together a script that reads the results from matchplay and builds a post with all the right info.

    It’s not enough to publish as a git repo or anything and I just wanted to have a place to keep it so it’s here for now.

    ben@odin ~> cat ~/bin/tcpp
    #!/bin/sh
    
    playersjson=$(curl -s "https://app.matchplay.events/api/tournaments/$1?includePlayers=1" \
        -H "Content-Type: application/json" \
        -H "Accept: application/json")
    
    finalsId=$(printf %s "$playersjson" | jq -r ".data.linkedTournamentId")
    standingsids=$(curl -s "https://app.matchplay.events/api/tournaments/$finalsId/standings" \
        -H "Content-Type: application/json" \
        -H "Accept: application/json" \
        | jq -r '.[] | .playerId')
    
    d=$(printf %s "$playersjson" | jq -r ".data.startUtc")
    shortdate=$(date --date "$d" +"%B %-d")
    ifpa=$(curl -s 'https://api.ifpapinball.com/v1/calendar/search?api_key=GET_YOUR_OWN&address=Traverse%20City&m=3')
    ifpatourney=$(printf %s "$ifpa" | jq -r ".calendar[] | select(.start_date == \"$(date --date "$d" +"%F")\").tournament_id")
    
    author=1
    excerpt="Results for $shortdate tourney"
    
    case $(date --date "$d" +"%a") in
        Thu)
            categories="58,54"
            ;;
        Mon)
            categories="58,52"
            ;;
        Sun)
            categories="58,51"
            author=8
            excerpt="Results for the $shortdate Belles tourney"
            ;;
        *)
            categories="4"
            ;;
    esac
    
    player1=$(printf %s "$playersjson" | jq -r ".data.players | .[] | select(.playerId == $(printf %s "$standingsids" | head -n1 | tail -n1)).name")
    player2=$(printf %s "$playersjson" | jq -r ".data.players | .[] | select(.playerId == $(printf %s "$standingsids" | head -n2 | tail -n1)).name")
    player3=$(printf %s "$playersjson" | jq -r ".data.players | .[] | select(.playerId == $(printf %s "$standingsids" | head -n3 | tail -n1)).name")
    player4=$(printf %s "$playersjson" | jq -r ".data.players | .[] | select(.playerId == $(printf %s "$standingsids" | head -n4 | tail -n1)).name")
    
    printf "https://tcpinball.org/wp-admin/post.php?action=edit&post="
    sudo -Hu www-data wp --path=/var/www/tcpinball.org \
        post create \
        --post_author="$author" \
        --post_category="$categories" \
        --post_title="$shortdate Results" \
        --post_excerpt="$excerpt" \
        --post_status=draft \
        --porcelain \
        --post_content="<!-- wp:paragraph -->
    <p>Format: Group Match Play</p>
    <!-- /wp:paragraph -->
    
    <!-- wp:table {\"hasFixedLayout\":false} -->
    <figure class=\"wp-block-table\"><table><thead><tr><th>Place</th><th>Player</th></tr></thead><tbody><tr><td>1st</td><td>$player1</td></tr><tr><td>2nd</td><td>$player2</td></tr><tr><td>3rd</td><td>$player3</td></tr><tr><td>4th</td><td>$player4</td></tr></tbody></table></figure>
    <!-- /wp:table -->
    
    <!-- wp:paragraph -->
    <p>See the full results on <a href=\"https://app.matchplay.events/tournaments/$1\">Match Play</a> - <a href=\"https://app.matchplay.events/tournaments/$finalsId\">Finals</a> (<a href=\"https://www.ifpapinball.com/tournaments/view.php?t=$ifpatourney\">IFPA</a>).</p>
    <!-- /wp:paragraph -->
    "

    Results table was built by dumping the content from a previous post.