Interactive/LiveUpdateCustom.py

# (C) Copyright 2011 Autodesk, Inc.  All rights reserved.
#
# Use of this software is subject to the terms of the Autodesk license
# agreement provided at the time of installation or download, or which
# otherwise accompanies this software in either electronic or hard copy
# form.

from UserCustomization   import UserCustomBase, theUserCustomization, CustomInfo
from DirectoryUtilities  import GetProductTemporaryDirectory
from GenericMenu         import GenericMenu
from awSupportApi        import Product

import XMLSaxReader
import webbrowser
import urllib2
import os.path

class LiveUpdateResponse:
    def __init__(self, request, doRefresh=True):
        self.myRequest = request
        self.myResult = None

    def refresh(self):
        self.myResult = None
        if self.myRequest is None:
            return self.myResult
        try:
            urlobj = urllib2.urlopen(self.myRequest.url())
            filename = os.path.join(GetProductTemporaryDirectory(),"liveupdate.xml")
            f = open(filename,"w")
            f.write(urlobj.read())
            f.close()
            self.myResult = XMLSaxReader.flatten(XMLSaxReader.parse(filename))
        except:
            print "Update failed from", self.myRequest.url()

        return self.myResult

    def result(self,forceRefresh=False):
        if forceRefresh or self.myResult is None:
            self.refresh()
        return self.myResult

    def numberOfUpdates(self,forceRefresh=False):
        self.result(forceRefresh)
        try:
            updates = self.myResult[('AvailableContent','Updates')]
            if len(updates) >= 1:
                return int(updates[0].NumberofUpdates)
        except:
            pass
        return 0


class LiveUpdateRequest:
    def __init__(self):
        self.myLine = None
        self.myRelease = None
        self.myMaster = None
        self.myBuild = None
        self.myURL = None


    def setToNativeVersion(self):
        product = Product.instance()
        if '32-bit' == product.getPlatformInfo():
            master = 'Win32'
        else:
            master = 'Win64'
        self.setVersion('ASC', product.getModelYear(), master,
                        ('%s-%s' % (product.getCutId(),
                                    product.getChangeSet())))
        return self


    def setVersion(self,line,release,master,build):
        self.myLine = line
        self.myRelease = release
        self.myMaster = master
        self.myBuild = build
        self.myURL = None


    def url(self):
        if self.myURL is not None:
            return self.myURL
        if (self.myLine is None or \
            self.myRelease is None or \
            self.myMaster is None or \
            self.myBuild is None):
            return None
        url = 'http://updates.autodesk.com/liveupdate/GetAvailableContent?productline=%s&release=%s&master=%s&build=%s' % (self.myLine,self.myRelease,self.myMaster,self.myBuild)
        return url

def instantiate():
    return LiveUpdateCustomization()

class LiveUpdateCustomization(UserCustomBase):
    def __init__(self):
        self.__myMenu = None
        self.__myMenuItem = None
        self.__myLiveUpdateMenu = None

        request = LiveUpdateRequest()
        request.setToNativeVersion()
        self.myResponse = LiveUpdateResponse(request)
        self.myNumberOfUpdates = self.myResponse.numberOfUpdates()


    def getInterpreter(self, isInteractive):
        return None


    def appendMenu(self, menuInterpreter):
        if True or self.myResponse.numberOfUpdates() > 0:
            self.__myLiveUpdateMenu = menuInterpreter.appendMenu(LiveUpdateMenu)
            # This line makes sure that menu items defined in other plug-ins will
            # be offered to attach themselves to the "LiveUpdateMenu" ID.
            theUserCustomization.appendMenuItems( u"LiveUpdateMenu", self.__myLiveUpdateMenu )
            self.__myMenuInterpreter = menuInterpreter


    def appendMenuItems(self,id,menu):
        if "LiveUpdateMenu" == id:
            nou = self.myResponse.numberOfUpdates()
            if 0 == nou:
                label = _( 'No Product Updates' )
            elif 1 == nou:
                label = _( 'Product Update Available' )
            elif nou < 6:
                label = _( '%s Product Updates Available' ) % (("", "", _("Two"), _("Three"), _("Four"), _("Five"))[nou])
            else:
                label = _( '%d Product Updates Available' ) % (nou)
            self.__myMenu = menu
            self.__myMenuItem = menu.appendItem(label, self.__onUpdate )


    def __onUpdate( self, event ):
        if self.myResponse is None:
            return

        xmlResult = self.myResponse.result()
        if xmlResult is None:
            return

        updates = xmlResult[('AvailableContent','Updates')]

        res = '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><title>%s</title></head><body>' % (_("Product Updates"))
        if (len(updates) < 1) or (0 == int(updates[0].NumberofUpdates)):
            res += '<center><h2>%s</h2></center>\n' % (_("Your product is up to date."))
        else:
            updates = xmlResult[('AvailableContent','Updates','Update')]
            n = len(updates)
            for update in updates:
                # res += "Name: %s" % (update.Name)
                res += '<h3>%s</h3>\n' % (update.DisplayName)
                res += '%s<br><br>' % (update['Description'][0].Description)
                res += '<A href="%s">%s</A>' % (update['File'][0].URL, update['File'][0].Name)

                res += '<br><br>'
                res += '<font size="-1">'
                res += _("Type: %s<br>") % (update.UpdateType)
                res += _("Severity: %s<br>") % (update.UpdateSeverity)
                res += _("Published: %s<br>") % (update.Publishdate)
                # res += "UpdateID %s<br>" % (update.UpdateID)
                # res += update['Description'][0].DescriptionTitle
                # res += update['File'][0].UpdateFileType
                res += '</font>'
                res += '<hr>'

        res += '</body></html>'

        filename = os.path.join(GetProductTemporaryDirectory(),"liveupdate.html")
        f = open(filename,"w")
        f.write(res)
        f.close()
        webbrowser.open(filename)


class LiveUpdateMenu(GenericMenu):
    def __init__(self, parentWindow):
        GenericMenu.__init__(self, parentWindow, menuId=u'LiveUpdateMenu')

    def getLabel(self):
        return _('Update(s)')


def info():
    customInfo = CustomInfo()
    customInfo.vendor = 'Autodesk'
    customInfo.version = '1.0'
    customInfo.api = '2012'
    customInfo.shortInfo = "Add a menu item that would show any available updates for the software."
    customInfo.longInfo = \
"""An Update(s) menu is added. It contains a menu item for the available product updates.
"""
    return customInfo