Pither.com / Simon
Development, systems administration, parenting and business

Sending tweets automatically from Python (and Django)

I run a local small business group that runs a couple of events every month. These events are either an evening social or a co-working day, always starting at the same time. One of the places I announce these events is on Twitter; however to get noticed on Twitter you need to post quite a lot, which is quite tedious (and difficult to remember) to do manually.

Yes, there are lots of social media scheduling tools that could reduce the task to a small weekly or monthly effort, but I don't like any of the current ones for two reasons:

  1. I have to actually schedule each tweet, picking a specific time. I don't really care too much about when the tweets go, I'd just like them to have a reasonable spread to try and catch assorting viewing times.
  2. I already store all the events in a little database for the website and copy-pasting or re-typing the date and time each month is really, really tedious (and error prone).

Hence I decided to create an auto-Tweeting script. With this Python twitter library it was really, really simple.

The code

The code below is in the form of a Django command, because that's what I needed but it could easily be extracted to just Python if you store the settings elsewhere and provide any template data differently (or have none at all)...

from datetime import datetime, timedelta
from django.core.management.base import BaseCommand, CommandError
from django.conf import settings
from random import randint, choice
import time
import twitter
import sys
from micropreneurs.models import Event


class Command(BaseCommand):
    help = 'Auto-tweeting cron'

    tweets = [
        "Join us {event.start_date:%a} {event.start_date.day} {event.location.twitter}\n9am-5pm free co-working\nhttp://www.redhill-micropreneurs.uk/coworking/\n#freelance #smallbiz #redhill #homeworker",
        "Self employed, freelancer, small business co-working day, {event.start_date:%a} {event.start_date.day} http://www.redhill-micropreneurs.uk/coworking/ {event.location.twitter}",
        "Our next free co-working is {event.start_date:%a} {event.start_date.day}, for small biz, freelancers and home workers in and around Redhill. http://www.redhill-micropreneurs.uk/coworking/",
        # You'll need lots more here or it will get repititive pretty quickly
    ]

    def add_arguments(self, parser):
        parser.add_argument(
            '--tweet',
            action='store_true',
            dest='tweet',
            default=False,
            help='Actually tweet!',
        )

    def handle(self, *args, **options):
        yes_no = randint(0, 28)  # 28 chances = 8am - 10pm, every 30 minutes
        if yes_no <= 26:  # 2 in 28 chance so hopefully about 2 tweets a day
            self.stdout.write('Choosing not to tweet this time')
            return

        delay = randint(0, 15)  # 0 to 15 minutes delay before we tweet
        self.stdout.write('Going to tweet but pausing for %s minutes...' % delay)
        time.sleep(delay * 60)

        tapi = twitter.Api(consumer_key=settings.TWEET_CONSUMER_KEY,
                           consumer_secret=settings.TWEET_CONSUMER_SECRET,
                           access_token_key=settings.TWEET_ACCESS_TOKEN_KEY,
                           access_token_secret=settings.TWEET_ACCESS_TOKEN_SECRET)

        template = choice(self.tweets)
        now = datetime.now()
        three_weeks = now + timedelta(days=21)
        event = Event.objects.filter(start_date__gte=now, start_date__lte=three_weeks).order_by('start_date').first()
        if event:
            tweet = template.format(event=event)
        else:
            self.stdout.write('Event missing, not tweeting')
            return

        self.stdout.write('Tweeting: %s' % tweet)
        if options['tweet']:
            tapi.PostUpdate(tweet)
        else:
            self.stdout.write('...not sent, dry run')

This script is designed to be run from cron, every thirty minutes from 8am to 10pm. The settings within it should cause roughly two tweets per day, at randomly chosen points. It will also wait a random number of minutes (between 0 and 15) before sending each tweet - just so they aren't all sent on the hour or at half past.

Other features I quite like:

Random choice of tweet template

Python makes it so simple to randomly select an item from a list:

template = choice(self.tweets)

Variables in the template

One of the key points was being able to insert varying data into the tweets automatically, Python .format() provides a really easy and powerful templating system. By providing just a single Django model like this:

tweet = template.format(event=event)

...means I can include all sorts of data such as days, dates and related object information, eg:

"Join us {event.start_date:%a} {event.start_date.day} {event.location.twitter}\n9am-5pm free co-working\nhttp://www.redhill-micropreneurs.uk/coworking/\n#freelance #smallbiz #redhill #homeworker",

The cron

The cron entry (with live tweeting enabled) might look like this:

*/30 8-21 * * * www-data /your-site-virtual-env/bin/python /your-site-app-path/manage.py auto_tweet --tweet >> /your-site-log-path/auto_tweet.log 2>&1

Credentials setup

There are four settings used in the script that provide the required Twitter API credentials. There's a walk through on how to obtain them here.

Add a comment