I need some help, please!
#1
I have been working on a small utility script to grab some information that is not readily available via labels. What I thought should be relatively easy has got me totally stumped. I would very very much appreciate if someone could look at my code and see where I've messed up, or any suggestions to make it easier/better.

PHP Code:
import xbmc
from xbmcgui import Window
from urllib import quote_plus
unquote_plus
import urllib
import re
import sys
import os
from traceback import print_exc


class Main:
    
# grab the home window
    
WINDOW Window10000 )

    
def _parse_argvself ):
        try:
            
# parse sys.argv for params
            
params dictarg.split"=" ) for arg in sys.argv].split"&" ) )
        
except:
            
# no params passed
            
params = {}
        
# set our preferences
        
self.ACTOR intparams.get"actorID""5" ) )
        
    
def __init__self ):
        
self._parse_argv()
        
#print "### Actor: %s" % self.ACTOR
        
self._fetch_movie_info()
                
    
def _fetch_movie_infoself ):
        
# sql statement for most watched        
            
sql_movies "SELECT t1.strRole, t2.c09, t2.c00, t2.strFileName, t2.strPath FROM actorlinkmovie t1 LEFT JOIN movieview AS t2 ON t1.idMovie = t2.idMovie WHERE t1.idActor=%d" % (self.ACTOR, )  
            print 
"### SQL: %s" sql_movies
        
# query the database
        
movies_xml xbmc.executehttpapi"QueryVideoDatabase(%s)" quote_plussql_movies ), )
        
# separate the records
        
movies re.findall"<record>(.+?)</record>"movies_xmlre.DOTALL )
        
# enumerate thru our records and set our properties
        
for countmovie in enumeratemovies ):
            
# separate individual fields
            
fields re.findall"<field>(.*?)</field>"moviere.DOTALL )
            
# set properties
            
print "### %s - %s" % (fields] ,fields26 ])
            
self.WINDOW.setProperty"ActorAppearances.%d.ActorRole" % ( count 1, ), fields] )
            
self.WINDOW.setProperty"ActorAppearances.%d.MovieTitle" % ( count 1, ), fields] )
            
self.WINDOW.setProperty"ActorAppearances.%d.MoviePoster" % ( count 1, ), fields] )
            
self.WINDOW.setProperty"ActorAppearances.%d.FileName" % ( count 1, ), fields] )
            
self.WINDOW.setProperty"ActorAppearances.%d.FilePath" % ( count 1, ), fields] )

if ( 
__name__ == "__main__" ):
    
Main() 

That's what I have. The idea is that the script will be passed the ActorID from XBMC, execute the SQL query and return all the movies that the actor has appeared in.

I'm confident the SQL is right, but for the life of me I can't get this working. Any help will be very much appreciated and get total credit for the solution. I eventually want to turn this into a bit of a utility script, with a few of these calls to grab information that isn't available in places that I need it.

Thanks!!!!!!

Blacklist
Reply
#2
Well, point number one, the first two lines in _fetch_movie_info() shouldn't be indented. Indentation is very important in Python. And when you define the class Main, it should be defined as Main() with brackets.

Aside from that, I would look into doing this in a way that doesn't use the HTTP API as it's deprecated, and if I recall, is potentially being removed completely in a few weeks.

Also, a better way to do this would be with a plugin. Check out Zsolt's tutorial on developing plugins. Part 2 is definitely the most beneficial part when it comes to actual development.
Reply
#3
blacklist:
Here is working one
Code:
import xbmc
from xbmcgui import Window
from urllib import quote_plus
import re

class Main:
    # grab the home window
    WINDOW = Window( 10000 )

    def _parse_argv( self ):
        try:
            self.ACTOR = int(sys.argv[1])
            return True
        except:
            return False
        
    def __init__( self ):
        self.WINDOW.setProperty( "ActorAppearances.Count", "0" )
        if self._parse_argv():
            self._fetch_actor_info()
                
    def _fetch_actor_info( self ):
        # sql statement for most watched        
        sql_actor_query = "SELECT t1.strRole, t2.c09, t2.c00, t2.strFileName, t2.strPath FROM actorlinkmovie AS t1 LEFT JOIN movieview AS t2 ON t1.idMovie = t2.idMovie WHERE t1.idActor=%d" % (self.ACTOR, )  
        print "### SQL: %s" % sql_actor_query
        # query the database
        actor_xml = xbmc.executehttpapi( "QueryVideoDatabase(%s)" % quote_plus( sql_actor_query ), )
        # separate the records
        actor_data = re.findall( "<record>(.+?)</record>", actor_xml, re.DOTALL )
        # enumerate thru our records and set our properties
        for count, actor in enumerate( actor_data ):
            # separate individual fields
            fields = re.findall( "<field>(.*?)</field>", actor, re.DOTALL )
            # set properties
            
            print "### %s in %s" % (fields[ 0 ] ,fields[ 2 ])
            self.WINDOW.setProperty( "ActorAppearances.%d.ActorRole" % ( count + 1, ), fields[ 0 ] )
            self.WINDOW.setProperty( "ActorAppearances.%d.MovieTitle" % ( count + 1, ), fields[ 2 ] )
            self.WINDOW.setProperty( "ActorAppearances.%d.MoviePoster" % ( count + 1, ), fields[ 1 ] )
            self.WINDOW.setProperty( "ActorAppearances.%d.FileName" % ( count + 1, ), fields[ 3 ] )
            self.WINDOW.setProperty( "ActorAppearances.%d.FilePath" % ( count + 1, ), fields[ 4 ] )
            
        self.WINDOW.setProperty( "ActorAppearances.Count", str(len(actor_data)) )

if ( __name__ == "__main__" ):
    Main()
  • fixed the indentation in _fetch_movie_info()
  • I wouldn't use so complex argument parsing if You only expect actor id as parameter
    Now just run script like this
    Code:
    RunScript(script.SCRIPT_NAME,0)
    where 0 is id of actor
  • in You SQL query You have "t1.strRole, t2.c09, t2.c00, t2.strFileName, t2.strPath" that is total of 5 values. Now this is how You access them:
    t1.strRole will be accessed fields[0] (index 0 is first item)
    t2.strPath will be accessed fields[4] (index 4 is fifth item, in this case last one)

    Because of that fields[26] in
    Code:
    print "### %s - %s" % (fields[ 2 ] ,fields[ 26 ])
    will cause it to crash (trying to reach item that is out of array size)
  • I also added ActorAppearances.Count property so items in list can have visible condition based on amount of appearances returned by script
  • Another suggestion would be not using Home Window to store properties, but it will work how it is now

I hope to see that in Your skin Smile
Reply
#4
I have refactored grajen3's script:

Code:
import re
import sys
import traceback
from urllib import quote_plus


import xbmc
from xbmcgui import Window

def fetch_actor_info(actor_id):
    # sql statement for most watched
    sql = (" SELECT alm.strrole, \n"
           "        mv.c09, \n"
           "        mv.c00, \n"
           "        mv.strfilename, \n"
           "        mv.strpath \n"
           " FROM   actorlinkmovie AS alm \n"
           "        LEFT JOIN movieview AS mv \n"
           "          ON alm.idmovie = mv.idmovie \n"
           " WHERE  alm.idactor = %d" % actor_id)
    print "### SQL: %s" % sql
    actor_xml = xbmc.executehttpapi("QueryVideoDatabase(%s)" % quote_plus(sql))
    # separate the records
    return re.findall("<record>(.+?)</record>", actor_xml, re.DOTALL)


def display_actor_info(window, actor_data):
    mapping = {
        "ActorRole": 0,
        "MoviePoster": 1,
        "MovieTitle": 2,
        "FileName": 3,
        "FilePath": 4,
    }
    for count, actor in enumerate(actor_data):
        # separate individual fields
        fields = re.findall("<field>(.*?)</field>", actor, re.DOTALL)
        for key, field_id in mapping.iteritems():
            window.setProperty("ActorAppearances.%d.%s" % (count + 1, key),
                               fields[field_id])
    window.setProperty("ActorAppearances.Count", str(len(actor_data)))


if (__name__ == "__main__"):
    home_window = Window(10000)
    home_window.setProperty("ActorAppearances.Count", "0")
    try:
        actor_id = int(sys.argv[1])
    except:
        print traceback.format_exc()
    else:
        data = fetch_actor_info(actor_id)
        display_actor_info(home_window, data)
It should do the same and is easier to read Smile
http://paste.pocoo.org/show/335862/
Reply
#5
Thank you guys, I appreciate the help Smile I am definatly a novice at python and am more hacking together things than anything else.

The httpapi depreciation scares me a bit, since a lot of the script I use are developed around httpapi. I also believe (correct me if I'm wrong) but JSON doesn't allow the type of SQL database calls I'm making here?

In the end, what I'm going to end up trying to create is a bit of a "utility belt" script that grabs some information not readily available to the skin. In this example, I have a custom dialog screen that is pulling actor information (thanks to ppic's script that scrapes wikipedia for the content) but I found that I had no access to the actor's media except through the cast listing (via xbmc) or the normal actor list (again xbmc generated). This little script lets me grab all of the relevent actor's media and allow playback.

Again, thanks very much for the feedback!
Reply

Logout Mark Read Team Forum Stats Members Help
I need some help, please!0