Short URLs with YOURLS for Yellow

· 5 min ·

As you've probably noticed, I thought I'd break up the flow of this blog a bit and put posts in the style of a microblog here in case I just want to get something off my chest that doesn't need a headline. During my research on blogs in general and microblogs in particular, I kept coming across IndieWeb. Among other things, they also recommend short URLs[1] so that there are enough characters left for texts for your posts if they (should) be shared on services such as Bluesky, Mastodon or Foursquare.

And as luck would have it, with kxe.one (KxE means Kurt & Edgar, which are the names of my sons) I have a very short URL behind which I have installed YOURLS to generate short URLs. So far only via the Short Menu[2] app for iOS. So I thought I'd build a YOURLS extension for my CMS and create short URLs for the microblog posts.

But I have to say that I haven't implemented it. It works but no, it has to wait until the microblog posts fit in here visually. So if you know a universal logo for short URLs, please let me know! I'm still not sure how I should display them. 🙄

YOURLS?

YOURLS[3] is short for "Your Own URL Shortener" and that basically says it all. And hell yes, Ozh deserves a prize for this homophonic abbreviation. It’s probably the only usable URL shortener for self-hosting in our solar system. The backend looks a bit old-fashioned, but let's be honest: a) nobody sees it except you and b) you hardly spend any time there. I've been using it for a while now and am completely satisfied, as features that are missing at first can be added via a plugin. If you're interested in the topic, give it a try. It's open source and free.

Shit, I'm raving here as if I'm involved in the project in some way, which of course I'm not. Anyone who knows me can confirm that I am a software user and not a developer.

So what was my approach?

I'm slowly warming up to creating extensions for Yellow and so it was clear to me that I would use the onParseContentShortcut() function to output the short URL to the post. This gives me the best opportunity to place the link in the layout file and also gives me complete freedom with the link name. Depending on which template I use it in (in case I want to extend the short URLs to post categories other than the microblog).

So my extension begins as follows:

<?php
// ShortUrl extension, https://github.com/pftnhr/yellow-shorturl

class YellowShorturl {
    const VERSION = "0.8.19";
    public $yellow;         // access to API

    public function onLoad($yellow) {
        $this->yellow = $yellow;
        $this->yellow->system->setDefault("ShorturlApi", "<your-yourls-host/yourls-api.php");
        $this->yellow->system->setDefault("ShorturlSecret", "<your secret signature from the Tools page of your YOURLS install");
    }

    public function onParseContentShortcut($page, $name, $text, $type) {
        $output = null;
        if ($name=="shorturl" && ($type=="block" || $type=="inline")) {
            list($shorturlLong, $shorturlKeyword, $shorturlTitle) = $this->yellow->toolbox->getTextArguments($text);
            $shorturlLong    = $this->yellow->lookup->normaliseUrl(
                                    $this->yellow->system->get("coreServerScheme"),
                                    $this->yellow->system->get("coreServerAddress"),
                                    $this->yellow->system->get("coreServerBase"),
                                    $page->location);
            $shorturlKeyword = $page->get("keyword");
            $shorturlTitle   = $page->get("title");
            $shorturlApi     = $this->yellow->system->get("ShorturlApi");
            $shorturlSecret  = $this->yellow->system->get("ShorturlSecret");

            $output .= $this->shortenWithYourls($shorturlLong, $shorturlKeyword, $shorturlTitle, $shorturlApi, $shorturlSecret);
        }
        return $output;
    }

The value for $shorturlLong ensures that the URL is passed without the /edit slug, which would appear because you are logged in to Yellow when you write a new article. The function onLoad($yellow) writes the URL to your YOURLS-API and your secret signature token into the yellow-system.ini (you only have to enter the correct values there).

To give the short URLs a custom name, I can set a keyword in the page settings. For example, you can create "https://sho.rt/CustomKey" with the following settings.

---
Title: Post title
Published: @datetime
Author: @username
Keyword: CustomKey
Layout: blog
Tag: Example
---
This is a new blog page.

So far, so simple. The next one took me a while and only worked in the end thanks to the plugin yourls-api-edit-url[4]:

    public function shortenWithYourls($shorturlLong, $shorturlKeyword, $shorturlTitle, $shorturlApi, $shorturlSecret) {
       $shortUrl = null;
       /*
        * YOURLS : sample file showing how to use the API
        * This shows how to tap into your YOURLS install API from *ANOTHER* server
        * not from a file hosted on the same server. It's just a bit dumb to make a
        * remote HTTP request to the server the request originates from.
        *
        * Rename to .php
        *
        */

       // EDIT THIS: your auth parameters
       $signature = $shorturlSecret;

       // EDIT THIS: the query parameters
       $url     = $shorturlLong;            // URL to shrink
       $keyword = $shorturlKeyword;         // custom Keyword (optional)
       $title   = $shorturlTitle;           // title (optional)
       $format  = 'json';                   // output format: 'json', 'xml' or 'simple'

       // EDIT THIS: the URL of the API file
       $api_url = $shorturlApi;


       // Init the CURL session
       $ch = curl_init();
       curl_setopt( $ch, CURLOPT_URL, $api_url );
       curl_setopt( $ch, CURLOPT_HEADER, 0 );            // No header in the result
       curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); // Return, do not echo result
       curl_setopt( $ch, CURLOPT_POST, 1 );              // This is a POST request
       curl_setopt( $ch, CURLOPT_POSTFIELDS, array(      // Data to POST
               'url'      => $url,
               'keyword'  => $keyword,
               'title'  => $title,
               'format'   => $format,
               'action'   => 'shorturl',
               'signature' => $signature
           ) );

       // Fetch and return content
       $data = curl_exec($ch);
       curl_close($ch);

       $data = json_decode( $data );

       // Do something with the result. Here, we just echo it.
       if ($data == null) {
            $chGet = curl_init();
            curl_setopt( $chGet, CURLOPT_URL, $api_url );
            curl_setopt( $chGet, CURLOPT_HEADER, 0 );            // No header in the result
            curl_setopt( $chGet, CURLOPT_RETURNTRANSFER, true ); // Return, do not echo result
            curl_setopt( $chGet, CURLOPT_POST, 1 );              // This is a POST request
            curl_setopt( $chGet, CURLOPT_POSTFIELDS, array(      // Data to POST
                  'url'      => $url,
                  'keyword'  => $keyword,
                  'title'  => $title,
                  'format'   => $format,
                  'action'   => 'geturl',
                  'signature' => $signature
              ) );

            // Fetch and return content
            $dataGet = curl_exec($chGet);
            curl_close($chGet);

            $dataGet = json_decode( $dataGet );
            $shortUrl = 'https://kxe.one/'.$dataGet->keyword;

       } else {

           $shortUrl = $data->shorturl;
       }

       return $shortUrl;
    }

The content is mainly based on the sample-Remote-api-call.txt, which is shipped with YOURLS. I adapted it to the passed variables and inserted another cURL session if the JSON array of the first cURL session is empty, which happens if $shorturlLong already exists in the YOURLS database. So the value 'action' => 'geturl' in the second cURL session only works if the plugin yourls-api-edit-url is installed! If anyone has a solution for this without a plugin, please send me an email.

I don't want to go into detail about what didn't work in the meantime because I simply can't put it into words. As it is now, it works and that makes me extremely happy because, as I mentioned at the beginning, I am not a developer.

You can find the complete code as a Yellow Extension on GitHub[5].


Reply via e-mail

Back to top