Skip to main content

One bash script to blog them all

·660 words·4 mins
Python Fun Meta
Table of Contents

One of my desired blog specs was automation. The first automation I made was make_entry.py, a script modelled on this blog’s example that would, from the command line, create a fresh new .md file with my Pelican template stuff filled-in. My latest little automation is a script I named picard.sh (because makeitso.sh was too annoying to type).

picard.sh automates the process of Pelican making -> publishing to my webhost -> updating Twitter. It’s super simple, and I’ll be using this blog entry as the first integration test/guinea pig.

Step 1: Pelican-make the blog
#

# picard.sh
# Jan 2018. Automate publishing + tweeting.

echo 'Pouring blog out into local angelaambroz/ dir'
make html

After creating this blog post, in Markdown and in my blog/content/ folder, I need to run make html to pour it into the local directory where the rest of my website is. This comes built-in with Pelican (docs).

Step 2: Securely copying my local website copy onto my webhost server, using ssh
#

Oh man, how I love SSH (secure shell)! I could go on and on about it. And I love scp (secure copy protocol), which lets you copy files and folders to remote servers. It’s awesome.

Before I could get picard.sh (or any bash scripting into remote servers) to work, then, I needed to get an SSH handshake set up between me and the webhost. I did this:

  1. Create new SSH keys, specific to my webhost’s server, with ssh-keygen.
  2. Put those keys on the server via the UI. This is similar to how it works on GitHub. Further reading: Adding a new SSH key to your GitHub account
  3. Set up my .ssh/config file to use only those website-specific keys when SSHing or SCPing into that server. Further reading: SSH - Too Many Authentication Failures. This was to troubleshoot a “too many attempts” disconnection I kept getting. It was trying all my other SSH keys.

Once all that was done, I could now securely connect to my website from the command line. Awesome! I copied a test file over with scp, and voila! Things were ready. I added the following to picard.sh:

echo 'SCPing over to angelaambroz.com'
scp -r /path/to/local/website/blog my_username@my_webhost:~/path/to/website/

Step 3: Let Twitter know
#

Okay, so I’m skipping over a Python script that I wrote, update_twitter.py, that tells the Twitter world about a new blog post when it happens. It’s not terribly interesting, or terribly different from my post on Making a Twitter bot. Here’s the only different stuff:

def _make_link(blog_slug, blog_date):
    """
    Example link: http://angelaambroz.com/blog/posts/2017/Dec/21/data_is_my_copilot/
    Twitter will handle link shortening via t.co
    (https://help.twitter.com/en/using-twitter/how-to-tweet-a-link)
    """

    base_url = 'http://angelaambroz.com/blog/posts'
    date = datetime.strptime(blog_date, '%Y-%m-%d %H:%M')
    year = date.year
    month = date.strftime('%b')
    day = date.day
    return f"{base_url}/{year}/{month}/{day}/{blog_slug}/index.html"

def tweet_about_blog(post, connection):
    """Tweet about post
    """
    robot_emoji = b'\xf0\x9f\xa4\x96'
    url = _make_link(post['slug'], post['date'])
    tweet = bytes(f"{post['blurb']} {url} ", 'utf-8') + robot_emoji
    connection.update_status(tweet)


def get_last_n_blog_entries(n=1):
    """Grab last n (default=1) blog entries from the content/ folders"""
    latest_blog_posts = sorted([x for x in os.listdir('content/') if ".md" in x])[-n:]

    title_list = []
    for blog_post in latest_blog_posts:

        with open(f"content/{blog_post}") as f:
            blog_list = f.readlines()

        title = [x for x in blog_list if 'Title: ' in x][0]
        slug = [x for x in  blog_list if 'Slug: ' in x][0]
        date = [x for x in  blog_list if 'Date: ' in x][0]
        title_list.append({
            'blurb': title.strip().replace('Title: ', 'New blog: '),
            'slug': slug.strip().replace('Slug: ', ''),
            'date': date.strip().replace('Date: ', '')
            })

    return title_list

The most interesting hm!-inducing stuff in this Python script were just:

  • Finding the the unicode (or is it hex? what is that thing?) for the robot_emoji.
  • List comprehensions are always nice? e.g. latest_blog_post = sorted([x for x in os.listdir('content/') if ".md" in x])[-n:]
  • I’m still in love with Python 3.6’s fancy print formatting, f"Hello, {variable_for_name}!".

All that said, it just pops into picard.sh like so:

echo 'Updating Twitter...'
python update_twitter.py

echo 'Done!'

And that’s it!

And, okay, I just realized I could have used publishconf.py or fabfile.py (both built-in Pelican publishing tools) for this… Oop!

Related

Automatic desktop backgrounds
·1482 words·7 mins
Tutorial Fun Python
One of my first Python projects was automating a daily desktop background.
Hello, Pelican!
·1161 words·6 mins
Tutorial Python Meta
For the past few months, I’d been looking to start a mostly-tech blog.