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:
- Create new SSH keys, specific to my webhost's server, with
ssh-keygen
. - 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
- 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!