[Debconf-video-commits] r422 - package/branches/pycon09/src

Ryan Verner xf-guest at alioth.debian.org
Tue Apr 14 07:05:54 UTC 2009


Author: xf-guest
Date: 2009-04-14 07:05:54 +0000 (Tue, 14 Apr 2009)
New Revision: 422

Added:
   package/branches/pycon09/src/blip.py
Log:
Blip script for automated publishing. Adapted from blip API example but curl used instead. Script needs some TLC

Added: package/branches/pycon09/src/blip.py
===================================================================
--- package/branches/pycon09/src/blip.py	                        (rev 0)
+++ package/branches/pycon09/src/blip.py	2009-04-14 07:05:54 UTC (rev 422)
@@ -0,0 +1,263 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""@brief Upload videos to blip.tv or update blip.tv posts
+
+    EDIT: Some modifications to use CURL.  This script needs cleanup.
+
+    This script can be used to post videos to blip.tv, or to upload additional
+    formats for existing posts, or to change the description of existing posts.
+    
+    The script uses ffmpeg2theora to (optionally) convert video files to Ogg Theora.
+    See http://v2v.cc/~j/ffmpeg2theora/.
+    
+    The script uses the blip.tv "REST Upload API". See http://blip.tv/about/api/.
+    
+    blip.tv uses item IDs to identify videos. For the video at
+    http://blip.tv/file/123456, the item ID is "123456". The code refers to
+    this ID as "video_id".
+    
+    Usage:
+    @code
+      blip_uploader.py [<video-id> [<filename>]]
+
+      # Entirely interactive (you are prompted for all required information):
+      blip_uploader.py
+        
+      # Upload alternate format to existing post:
+      blip_uploader.py 123456 alternate_format.ogg
+                    
+      # Upload new video:
+      blip_uploader.py "" new_video.mpg
+    @endcode
+"""
+
+import getpass
+import httplib
+import mimetypes
+import os
+import re
+import sys
+import urllib2
+import urlparse
+from xml.dom.minidom import parseString
+from xml.sax.saxutils import unescape
+
+BLIP_UPLOAD_URL = "http://blip.tv/file/post"
+
+MULTIPART_BOUNDARY = "-----------$$SomeFancyBoundary$$"
+
+def CurlUpload(BLIPURL, fields, file):
+   cline = "curl -F file=@\"%s\" " % (file)
+   for field_name, value in fields.iteritems():
+      cline = "%s -F %s=%s " % (cline, field_name, re.escape(value))
+   cline = "%s %s" % (cline, BLIPURL)
+   result = os.popen(cline, "r")
+   return result.read()
+
+def PostMultipart(url, fields, files):
+    """@brief Send multi-part HTTP POST request
+    
+    @param url POST URL
+    @param fields A dict of {field-name: value}
+    @param files A list of [(field-name, filename)]
+    @return Status, reason, response (see httplib.HTTPConnection.getresponse())
+    """
+    content_type = 'multipart/form-data; boundary=%s' % MULTIPART_BOUNDARY
+    data = []
+    for field_name, value in fields.iteritems():
+        data.append('--' + MULTIPART_BOUNDARY)
+        data.append('Content-Disposition: form-data; name="%s"' % field_name)
+        data.append('')
+        data.append(value)
+    for (field_name, filename) in files:
+        data.append('--' + MULTIPART_BOUNDARY)
+        data.append('Content-Disposition: form-data; name="%s"; filename="%s"'
+                    % (field_name, filename))
+        data.append('Content-Type: %s' % GetMimeType(filename))
+        data.append('')
+        data.append(open(filename).read())
+    data.append('--' + MULTIPART_BOUNDARY + '--')
+    data.append('')
+    data = "\r\n".join(data)
+
+    host, selector = urlparts = urlparse.urlsplit(url)[1:3]
+    h = httplib.HTTPConnection(host)
+    h.putrequest("POST", selector)
+    h.putheader("content-type", content_type)
+    h.putheader("content-length", len(data))
+    h.endheaders()
+    h.send(data)
+    response = h.getresponse()
+    return response.status, response.reason, response.read()    
+
+def GetMimeType(filename):
+    return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
+
+def Upload(video_id, username, password, title, description, filename):
+    """@brief Upload to blip.tv
+    
+    @param video_id Either the item ID of an existing post or None to upload
+        a new video
+    @param username, password
+    @param title New title of the post
+    @param description New description of the post
+    @param filename Filename of the video to upload (if a @a video_id is specified),
+        this file is uploaded as an additional format to the existing post)
+    @return Response data
+    """
+    fields = {
+        "post": "1",
+        "skin": "xmlhttprequest",
+        "userlogin": "%s" % username,
+        "password": "%s" % password,
+        "item_type": "file",
+        "title": "%s" % title.encode("utf-8"),
+        "description": "%s" % description,
+	"topics": "python, pycon, conference, chicago, 2009",
+	"license": "13",
+	"categories_id": "10",
+        }
+    if video_id:    # update existing
+        fields["id"] = "%s" % video_id
+        file_field = "file1"
+    else:           # new post
+        file_field = "file"
+    if filename:
+        fields[file_field + "_role"] = "Web"
+        files = filename #[(file_field, filename)]
+    else:
+        files = []
+    
+    print "Posting to", BLIP_UPLOAD_URL
+    print "Please wait..."
+
+#    status, reason, response = PostMultipart(BLIP_UPLOAD_URL, fields, files)
+    response = CurlUpload(BLIP_UPLOAD_URL, fields, files)
+    print "Done."
+
+    return response
+        
+def AskForVideoId():
+    video_id = None
+    while video_id is None:
+        video_url = raw_input("Enter blip.tv video ID or URL\n  (e.g., "
+                              "'123456' or 'http://blip.tv/file/123456'),\n"
+                              "  or press RETURN to upload a new video: ")
+        if not video_url:
+            return None
+        m = re.match(r"[^\d]*(\d+).*", video_url)
+        if m:
+            video_id = m.group(1)
+        else:
+            print "Invalid format"
+    return video_id
+
+def AskYesNo(question, default=True):
+    while True:
+        if default == True:
+            options = "[Y/n]"
+        else:
+            options = "[y/N]"
+        yes_no = raw_input(question + " " + options + " ")
+        if not yes_no:
+            return default
+        elif yes_no in ["Y", "y"]:
+            return True
+        elif yes_no in ["N", "n"]:
+            return False
+            
+def GetTextFromDomNode(node):
+    rc = ""
+    for n in node.childNodes:
+        if n.nodeType == node.TEXT_NODE or n.nodeType == node.CDATA_SECTION_NODE:
+            rc = rc + n.data
+    return rc
+
+def GetVideoInfo(video_id):
+    """@brief Return information about the video
+    
+    @param video_id blip.tv item ID
+    @return A tuple of
+        @a title (string),
+        @a description (string),
+        @a link (URL to video as a string),
+        @a embed_code (HTML <embed> code as a string),
+        @a embed_id (the part of the <embed> code that's used with the Drupal filter,
+            e.g., "AbCcKIuEBA"),
+        @a existing_mime_types (a dict of {mime_type: list_of_file_urls}
+            containing the URLs that are currently part of the post)
+    """
+    url = 'http://blip.tv/file/%(video_id)s?skin=rss' % locals()
+    print "Loading", url, "..."
+    xml_code = urllib2.urlopen(url).read()
+    rss = parseString(xml_code)
+    channel = rss.getElementsByTagName("channel")[0]
+    item = channel.getElementsByTagName("item")[0]
+    title = GetTextFromDomNode(item.getElementsByTagName("title")[0])
+    description = unescape(
+        GetTextFromDomNode(item.getElementsByTagName("blip:puredescription")[0]))
+    link = GetTextFromDomNode(item.getElementsByTagName("link")[0])
+    embed_code = GetTextFromDomNode(item.getElementsByTagName("media:player")[0])
+    embed_id = None
+    m = re.search(r"http://blip.tv/play/(\w+)", embed_code)
+    if m:
+        embed_id = m.group(1)
+
+    existing_mime_types = {}
+    media_group = item.getElementsByTagName("media:group")[0]
+    for content in media_group.getElementsByTagName("media:content"):
+        existing_mime_types.setdefault(content.attributes["type"].value, []).append(
+            content.attributes["url"].value)
+        
+    return title, description, link, embed_code, embed_id, existing_mime_types
+
+def DisplayVideoInfo(title, link, embed_code, embed_id, existing_mime_types):
+    print "Title           =", title
+    print "Link            =", link
+    if embed_id:
+        print "Embed ID        =", embed_id
+    else:
+        print "Embed ID        = <The video hasn't been converted to Flash yet>"
+    if existing_mime_types:
+        print "Files           ="
+        for urls in existing_mime_types.itervalues():
+            for url in urls:
+                print "    " + url
+
+def ConvertToOggTheora(filename):
+    out_filename = os.path.splitext(filename)[0] + os.extsep + "ogg"
+    cmd = 'ffmpeg2theora -o "%(out_filename)s" "%(filename)s"' % locals()
+    print "Running", cmd, "..."
+    exit_code = os.system(cmd)
+    if exit_code:
+        print "Error: Command returned with code %r" % (exit_code,)
+        sys.exit(1)
+    return out_filename
+
+def GetDescription(default):
+    if os.path.exists("description.txt"):
+        print ''
+        print 'Taking description from file "description.txt"...'
+        default = open("description.txt").read()
+    print "Current description:\n  {{{%s}}}" % default
+    print ""
+    desc = raw_input(
+        'Type a new one-line description or press RETURN to keep the current one\n'
+        '  (If you need more than one line, press Ctrl+C to abort,\n'
+        '  create a file named "description.txt" and run again): ')
+    return desc or default
+
+#def Main():
+#    if len(sys.argv) < 6:
+#        print "USAGE: video_id (use \"\" for new videos) username password title description filename"
+#        print " EXAMPLE: $0 \"\" john pass123 \"Some talk - Some author\" \"This is a talk about something.\" johntalk.mov" 
+#        return 1
+#    else:
+#        response = Upload(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5], sys.argv[6]);
+#        print "Server response:\n  {{{%s}}}" % response
+#        return 0
+#
+#if __name__ == "__main__":
+#    sys.exit(Main())
+


Property changes on: package/branches/pycon09/src/blip.py
___________________________________________________________________
Added: svn:executable
   + *




More information about the Debconf-video-commits mailing list