#!/usr/bin/python
"""
Written by Craig Younkins
Version 1.0 - upload_to_s3.py

Takes a list of filenames via standard input and uploads them to the Amazon S3
bucket provided as the sole parameter. It notifies the user via libnotify, and
is intended for background use. It also sets the clipboard text to the url of 
the file after a successful upload.

Requires S3.py:
    http://developer.amazonwebservices.com/connect/entry.jspa?externalID=134&categoryID=47

Usage:
    cd /directory/with/media/files/
    find | grep -v ".svn" | python /path/to/update_s3.py

Before you use this, change the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY 
variables at the top of the file.

You can run this multiple times on the same files -- it'll just override the
files that were in your S3 account previously.

------------
Changelog
------------

1.0 - 10/10/08 - Initial release
"""

import sys
import mimetypes
import os.path
import pygtk
import gtk
import urllib
import re
import pynotify

import S3 # Get this from Amazon

pygtk.require('2.0')

#
# CHANGE YOUR S3 ACCESS KEY AND SECRET ACCESS KEY HERE
#
AWS_ACCESS_KEY_ID = ''
AWS_SECRET_ACCESS_KEY = ''

INFO_TIMEOUT = 5000
ERROR_TIMEOUT = 20000

def close_cb(n,action):
	n.close()

def upload_s3():
    bucket_name = sys.argv[1]
    base_url = "http://%s.s3.amazonaws.com/" % bucket_name

    conn = S3.AWSAuthConnection(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
    clipboardText = ''

    # Cheat
    p = re.compile('<Message>(.*)</Message>')

    for line in sys.stdin:
        # file = full path
        file = os.path.normpath(line[:-1])
        if file == '.' or not os.path.isfile(file):
            continue # Skip this, because it's not a file.

        # filename = File without path. ex: moo.mp3
        filename = os.path.basename(file)
        filedata = open(file, 'rb').read()

        # Guess content type
        content_type = mimetypes.guess_type(file)[0]
        if not content_type:
            content_type = 'text/plain'

        # Alert user we're uploading
        notifyText = "Uploading %s to S3 bucket %s" % (filename, bucket_name)
        print notifyText 
        notify("Uploading", notifyText, INFO_TIMEOUT)

        # Upload
        res = conn.put(bucket_name, filename, S3.S3Object(filedata),
            {'x-amz-acl': 'public-read', 'Content-Type': content_type})

        if res.message != '200 OK':
            found = p.findall(res.message)[0]
            if found:
                notifyText = "There was an error in sending %s.\nResponse: %s"\
                % (filename,found)
            else:
                notifyText = "There was an error in sending %s."
            print notifyText + "\n"
            notify("Error", notifyText, ERROR_TIMEOUT)
        else: # Uploaded successfully
            url = base_url + urllib.quote(filename) 
            notifyText = "Upload of %s was successful.\n" % filename
            notifyText += "Access it <a href=\"%s\">here</a>." % url

            print notifyText + "\n"
            notify("Success", notifyText, INFO_TIMEOUT)

            # Append it to our clipboard data
            clipboardText += url + "\n"

    setClipboard(clipboardText)

def usage():
    print "Usage:\n"
    print "%s <bucket>" % sys.argv[0]
    print "Push filenames to stdin."
    print "Ex: find | grep -v \".svn\" | python /path/to/%s\n" % sys.argv[0]
    print "*NOTE*: You MUST set your S3 access key and secret access key in"
    print "the script before using it."

def setClipboard(text):
    # get the clipboard
    clipboard = gtk.clipboard_get()

    # set the clipboard text data
    clipboard.set_text(text)

    # make our data available to other applications
    clipboard.store()

def notify(title, body, timeout):
    pynotify.init("Moo")
    n = pynotify.Notification(title, body)
    n.add_action("close", "Close", close_cb)
    n.set_timeout(timeout) 
    n.set_urgency(pynotify.URGENCY_NORMAL)
    n.show()

if __name__ == "__main__":
    if not AWS_ACCESS_KEY_ID or not AWS_SECRET_ACCESS_KEY:
        usage()
        sys.exit()

    if len(sys.argv) != 2:
        usage()
    else:
        upload_s3()

