# # main.py : The pipes that power the potater # Copyright (C) 2010 Curtis Lassam # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . import os import json import docutils.core import shutil import datetime import subprocess import html_view import feed_view def get_json_files( target ): """ Returns a list of json files in the target directory """ files = os.listdir( target ) return filter( lambda filename: filename.endswith('.json'), files ) def get_json_numbers( json_files): """ Takes a list of json files: ['1.json', '2.json', '3.json', 'fuck.json']. Returns a sorted list of numbers, [1,2,3]. """ json_numbers = map( json_to_number, json_files) json_numbers.sort() return filter( lambda n: n != None, json_numbers) def json_to_number( json_file ): """ Takes a json filename: '1.json'. Returns an integer representation or None. """ n = None try: n = int(json_file.strip('.json')) except: n = None return n def get_top10_object( json_file ): """ Open a json_file, return the 'top10' object Contains: author (string), date(ISO date string), blurb(restructured text string) top10(array of objects containing title, link, body, category strings) """ f = open( json_file ) f_json = f.read() obj = json.loads( f_json ) if obj.has_key('top10'): obj['top10'].reverse() f.close() defaults( obj ) top10_rst( obj ) unicode_strip( obj ) date_to_string( obj ) return obj def write_to_file( string, file ): f = open( file, 'w') f.write( string ) f.close() def rst_to_html( rst_string ): """ Convert a restructured text swatch into HTML """ parts = docutils.core.publish_parts( source=rst_string, settings_overrides={'output_encoding':'latin-1'}, writer_name='html' ) return parts['html_body'] def top10_rst( top10 ): """ Takes a top10 object and converts it's blurb and item->body parts from restructured text to HTML""" if top10.has_key('blurb'): top10['blurb'] = rst_to_html( top10['blurb'] ) for item in top10['top10']: if item.has_key('body'): item['body'] = rst_to_html( item['body'] ) def unicode_strip( top10 ): """ Convert all unicode to ascii strings """ for item in top10: if type(top10) == type({}): k = top10[item] else: k = item if type(k) == type([]) or type(k) == type({}): k = unicode_strip( k ) elif type(item) == type(u'boop'): k = k.encode('latin-1', 'xmlcharrefreplace') if type(top10) == type({}): top10[item] = k else: item = k return top10 def date_to_string( top10 ): """ Converts the ISO-formatted date string in the top10 object into a pretty string. """ if top10.has_key('date'): ymd = top10['date'].split("-") dt = datetime.date( int(ymd[0]), int(ymd[1]), int(ymd[2]) ) top10['date'] = dt.strftime('%A, %B %d, %Y') def defaults( top10 ): """ Adds default values to a top10 object """ if not top10.has_key('date'): top10['date'] = datetime.date.today().isoformat() if not top10.has_key('blurb'): top10['blurb'] = "Nothin' to say today!" if not top10.has_key('author'): top10['author'] = "Curtis Lassam" if not top10.has_key('top10'): top10['top10'] = [] for item in top10['top10']: if not item.has_key('link'): item['link'] = "http://www.google.ca" if not item.has_key('title'): item['title'] = "Untitled Link" if not item.has_key('body'): item['body'] = "I liked this link, but I forgot to write down why." if not item.has_key('category'): item['category'] = "Misc" def main(): subprocess.call(['bash', 'clean.sh']) #Get a list of all JSON files json_files = get_json_files("json") json_numbers = get_json_numbers( json_files) n_last = max(json_numbers) n_first = min(json_numbers) # Make a temporary directory os.mkdir('temp') #Produce 1.html through N.html for i in range(0, len(json_numbers) ): obj = get_top10_object( "json/"+str(json_numbers[i])+".json" ) if (i+1) < len(json_numbers): obj['next'] = json_numbers[i+1] if (i-1) >= 0: obj['prev'] = json_numbers[i-1] obj['first'] = n_first obj['last'] = n_last obj['location'] = "http://potater.com/"+str(json_numbers[i])+".html" html = html_view.top10_to_html( obj ) write_to_file( html, "temp/"+str(json_numbers[i])+".html" ) #Produce index.html obj = get_top10_object( "json/"+str(n_last)+".json" ) if( len(json_numbers) - 2 >= 0 ): obj['prev'] = json_numbers[ len(json_numbers) - 2 ] obj['first'] = n_first obj['last'] = n_last obj['location'] = "http://potater.com/index.html" html = html_view.top10_to_html( obj ) write_to_file( html, "temp/index.html") #produce feed.xml first_in_feed = 0 if ( len(json_numbers)-10 > 0 ): first_in_feed = len(json_numbers)-10 last10_top10s = [] for i in range(first_in_feed, len(json_numbers) ): obj = get_top10_object( "json/"+str(json_numbers[i])+".json" ) obj['location'] = "http://potater.com/"+str(json_numbers[i])+".html" obj['html'] = feed_view.top10_to_html( obj ) #use the unix timestamp on the json files to determine the last time they were modified obj['last_modified'] = datetime.datetime.fromtimestamp( os.path.getmtime( "json/"+str(json_numbers[i])+".json" )).isoformat() last10_top10s.append( obj ) feed = feed_view.generate_feed( last10_top10s ) write_to_file(feed, "temp/feed.xml") #copy everything into temp try: shutil.copytree( "images", "temp/images", ignore=shutil.ignore_patterns('.svn') ) except: print "temp/images already exists or could not be created." try: shutil.copy ("style.css", "temp/style.css" ) except: print "temp/style.css already exists or could not be created." try: shutil.copytree( "json", "temp/json", ignore=shutil.ignore_patterns('.svn') ) except: print "temp/json already exists or could not be created." #if this has all happened without error, deploy to live subprocess.call(['bash', 'deploy.sh']) subprocess.call(['bash', 'clean.sh']) if __name__ == "__main__": main()