#!/usr/bin/env python ############################################################################## ## Python script for taking links from del.icio.us and posting them to your ## Movable Type blog. This script can be totally configured via a ## configuration file - 'delish2mt.cfg'. Please refer to the sample file for ## reference. There are also several command-line parameters that can affect ## how this script operations - invoke this script with the '-h' parameter ## to view the help. ## ## This script requires the 'DeliciousWS.py' and 'MTBlog.py' python modules ## in order to function properly. ## ## By Andy Reitz , February 7th, 2008. ## URL: http://redefine.dyndns.org/~andyr/blog/archives/2008/02/delish2mt.html ############################################################################## import sys import DeliciousWS __verbose = False __debug = False ## ## Helper methods ## # This method generates a string in the form of 'Links for February # 7th, 2008'. There is probably a more pythonic way to do the day # suffix thing, but I couldn't find one, so I just did it myself. def generatePostTitle(): import datetime today = datetime.date.today() #today = datetime.datetime(2008, 01, 3) day = today.day # 1st, 21st, 31st # 2nd, 22nd # 3rd suffix = "" if day == 1 or day == 21 or day == 31: suffix += "st" elif day == 2 or day == 22: suffix += "nd" elif day == 3: suffix += "rd" else: suffix += "th" suffix += "" title = "Links for " + today.strftime("%A %B ") + "%d%s, %d" % (today.day, suffix, today.year) return (title) # Print the message if verbosity is turned on. def printv(str): if __verbose: print str.encode('ascii', 'replace') # Print the message if debugging is turned on. def printd(str): if __debug: print "DBG: %s" % str.encode('ascii', 'replace') ### ### MAIN PROGRAM ### # Parse the command-line arguments. The result will be in the 'options' object. # # Adapted from: http://docs.python.org/lib/module-optparse.html from optparse import OptionParser parser = OptionParser(usage="usage: %prog --cfgfile=FILE [options]") parser.add_option("-f", "--cfgfile", dest="cfgfile", help="Configuration file (default: 'delish2mt.cfg')", metavar="FILE", default="delish2mt.cfg") parser.add_option("-q", "--quiet", action="store_false", dest="verbose", default=True, help="don't print status messages to stdout") # FIXME: someday. #parser.add_option("--nomodify", action="store_false", dest="nomodify", default=False, help="Don't modify del.icio.us or MT. Print what would occur.") parser.add_option("-d", "--debug", action="store_true", dest="debug", default=False, help="Print debugging messages to STDOUT.") (options, args) = parser.parse_args() __verbose = options.verbose __debug = options.debug # Parse the config file. The result will be in the 'cfg' object. # # Adapted from: http://docs.python.org/lib/RawConfigParser-objects.html import ConfigParser cfg = ConfigParser.ConfigParser() configFilesRead = cfg.read([options.cfgfile]) printv("Succesfully read cfg file: %s" % configFilesRead) if len(configFilesRead) == 0: print "ERROR: Unable to parse config file '%s'! Please specify a valid config file." % options.cfgfile sys.exit(1) printd("configured del.icio.us Username: %s" % cfg.get("del.icio.us", "username")) # Create a new delicious object. delish = DeliciousWS.DeliciousWS(cfg.get("del.icio.us", "username"), cfg.get("del.icio.us", "password")) delish.setDebug(__debug) if cfg.get("del.icio.us", "api_endpoint"): printd("configured del.icio.us API endpoint is: %s" % cfg.get("del.icio.us", "api_endpoint")) delish.setAPIEndpoint(cfg.get("del.icio.us", "api_endpoint")) else: printd("using default del.icio.us API endpoint: %s" % delish.getAPIEndpoint()) if cfg.get("del.icio.us", "api_realm"): printd("configured del.icio.us API realm is: %s" % cfg.get("del.icio.us", "api_realm")) delish.setAPIRealm(cfg.get("del.icio.us", "api_realm")) else: printd("using default del.icio.us API endpoint: %s" % delish.getAPIRealm()) printd("configured mt Username: %s" % cfg.get("mt", "username")) printd("configured mt url: %s" % cfg.get("mt", "XMLRPC_URL")) printd("configured mt blogID: %s" % cfg.get("mt", "blogID")) # Fetch the links from delicious for the given tag. newLinks = delish.fetchLinksForTag (cfg.get("del.icio.us", "tag")) printv("Found the following links on del.icio.us:") printd("num links found: %i; num needed: %i" % (len(newLinks), int(cfg.get("del.icio.us", "numLinksRequired")))) if len(newLinks) < int(cfg.get("del.icio.us", "numLinksRequired")): printv("Only %s links were found on del.icio.us. This is less than the required number\nof %s. Doing nothing." % (len(newLinks), cfg.get("del.icio.us", "numLinksRequired"))) sys.exit(0) # Generate the body of the new blog post. This is all basically hard-coded. # In the future, it might be more templatized. newPostBody = "\n" # Generate the title of the blog post title = generatePostTitle() # If debug mode is enabled, we'll print some fancy stuff here. printd("==============================") printd("Title: %s" % title) printd("New post:") printd(newPostBody) printd("==============================") newPost = {} newPost['title'] = title newPost['description'] = newPostBody # Import my blog module, and prepare to make a new posting to the configured # Movable Type blog. import MTBlog blg = MTBlog.MTBlog (cfg.get("mt", "XMLRPC_URL"), cfg.get("mt", "blogID"), cfg.get("mt", "username"), cfg.get("mt", "password")) blg.setDebug(__debug) mtPostID = blg.postToBlog (newPost) printv("New post written to MT. Post ID: %s" % mtPostID) # Set category to be 'Links'. catOut = blg.setCategory (mtPostID, cfg.get("mt", "category")) printd("Set category result: %s" % catOut) # Modify the links that have been posted, so that they aren't picked up on a # subsequent run of this program. delish.modifyTagForLinks (newLinks, cfg.get("del.icio.us", "tag"), cfg.get("del.icio.us", "postedTag")) printv("del.icio.us links set from tag '%s' to tag '%s'" % (cfg.get("del.icio.us", "tag"), cfg.get("del.icio.us", "postedTag"))) printv("Program finished successfully.")