M0AGX / LB9MG

Amateur radio and embedded systems

Scheduling posts with Pelican

Pelican has no facility for scheduling posts. However, it is very easy to do it with basic shell scripting and cron. I started by adding Scheduled: yes field to the draft post. The header before publishing looks like:

1
2
3
4
5
6
Title: Scheduling posts with Pelican
Slug: scheduling-posts-with-pelican
Date: 2023-07-23
Category: Misc
Status: draft
Scheduled: yes

Avoiding a new status (like here) and adding a separate Scheduled: yes field avoids the problem that Pelican will ignore a file unless the status is draft or published. The extra field is simply ignored. I still can generate the drafts with a future date without issues. The magic script is:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/bin/sh
git pull
git restore pelicanconf.py
TIMESTAMP_NOW=`date '+%s'`
#File and directory names can not contain spaces!
for FILENAME in $(find ./content/articles -name \*.md); do
    if head -n 7 $FILENAME | grep -q '^Scheduled: yes$'; then
        DATE_SCHEDULED=`head -n 7 $FILENAME | grep '^Date: ' | cut -d ' ' -f 2`
        TIMESTAMP_SCHEDULED=`date '+%s' -d $DATE_SCHEDULED`

        echo -n "Scheduled $FILENAME on $DATE_SCHEDULED"

        if (( $TIMESTAMP_NOW > $TIMESTAMP_SCHEDULED )); then
            echo " - publishing"
            sed -i -e '1,7{s/^Status: draft$/Status: published/}' -e '1,7{/^Scheduled: yes$/d}' $FILENAME
            make rsync_upload
            git commit $FILENAME -m "Autopublish $FILENAME"
            git push
            break #publish only one article per script invocation
        else
            echo " - not yet"
        fi
    fi
done

I keep my blog source in git so the script tries to pull the latest changes. My "development" machine is not the same as the "build" machine. In case I left pelicanconf.py with relative paths the script tries to restore it. Then, grep is executed over all .md files in content/articles looking for files containing Scheduled: yes in the first 7 lines only. This avoids the problem if an article has Scheduled: yes more than once (like this very article). Next, another grep invocation with cut extracts the date. The date is converted to a Unix timestamp and compared against the current timestamp. If current timestamp is larger than the one in the file then the article is processed by sed. Status draft is changed to published and the line containing Scheduled: yes is deleted from the file. This only applies to the first 7 lines of the article. After the file is changed the makefile executes Pelican rebuild and upload. The modified file is committed to git and pushed. The script exits after finding a single file to publish. I don't intend to autopublish multiple articles in a single day. If the script is executed daily then the next invocation would publish the other article with an identical date.

I release the code into public domain.