MythDataGrabber

From MythTV Official Wiki
Jump to: navigation, search

This Python script is a work in progress --Outleradam 03:06, 19 October 2010 (UTC)

MythDataGrabber is designed to take an input of a file and output database information and commercial skip data in a "var = value" format.

MythDataGrabber

This script was originally designed as a database interface for mythicalLibrarian.

Inputs

mythdatagrabber --filename=file.ext : returns information to a file
   --DBHostName        : sets the DB Host, default: localhost
   --DBName            : sets the DB Name, default: mythconverg
   --DBUserName        : sets the User Name, default: mythtv
   --DBPassword        : sets the Password, default: mythtv
   --DBPin             : sets the Pin, default: 0
   --writeFile         : don't display output, write to ./showdata.txt
   --output=file.txt   : sets the output, default: ./showData.txt
   --version|-v|-ver   : displays version information
example:
$ mythdatagrabber 1000_20101010101010.mpg --DBHostName=localhost --DBName=mythconverg --DBUserName=mythtv --DBPassword=mythtv --writeFile --output=/home/myfile.txt

Outputs

mythtv@XBMC-live:~$ /usr/local/bin/MythDataGrabber --filename='1045_20101005120000.mpg' --DBHostName='192.168.1.110' --DBName='mythconverg' --DBUserName='mythtv' --DBPassword='mythtv' --DBPin="" --Display
Establishing database connection
chanid = "1045"
starttime = "2010-10-05 12:00:00"
endtime = "2010-10-05 13:00:00"
title = "Caprica"
subtitle = "Reins of a Waterfall"
description = "Amanda's public admission about Zoe's role in the bombing ignites a media backlash against the Graystones; Sam and Joseph confront Daniel."
category = "Science fiction"
hostname = "XBMC-live"
bookmark = "0"
editing = "0"
cutlist = "0"
autoexpire = "0"
commflagged = "1"
recgroup = "Default"
recordid = "21"
seriesid = "EP01213751"
programid = "EP012137510003"
lastmodified = "2010-10-05 12:00:02"
filesize = "1754496464"
stars = "0.0"
previouslyshown = "1"
originalairdate = "2010-02-05"
preserve = "0"
findid = "0"
deletepending = "0"
transcoder = "0"
timestretch = "1.0"
recpriority = "98"
basename = "1045_20101005120000.mpg"
progstart = "2010-10-05 12:00:00"
progend = "2010-10-05 13:00:00"
playgroup = "Default"
profile = "Default"
duplicate = "1"
transcoded = "0"
watched = "0"
storagegroup = "Default"
bookmarkupdate = "None" 

startdata[0] = "13663"
startdata[1] = "32548"
startdata[2] = "51539"
startdata[3] = "64846"
startdata[4] = "79186"
stopdata[0] = "18660"
stopdata[1] = "37724"
stopdata[2] = "55599"
stopdata[3] = "71311"
stopdata[4] = "85012"
Operation complete

If --Display is not specified, MythDataGrabber will create a file called ./showData.txt and dump it's information there.

Examples

BASH:

mkfifo ./DBOut                                    #create a named pipe called DBOut
MythDataGrabber --filename="myfile.ext">dbOut     #put the output from MythDataGrabber into the pipe
while read var equals value                       #split the output into 3 parts, variable, equals sign, and value
do
   test "$equals" = "=" && declare $var=$value    #if the variable "equals" is "=" then declare variable = value
done < ./DBOut                                    #port the named pipe into the while loop

#rename the variables for use in your program
MovieAirDate=$airdate; OriginalAirDate=$originalairdate; ShowCategory=$category; Stars=$stars; Plot=$description; Zap2itSeriesID=$seriesid; ProgramID=$programid; ChanID=$chanid; ShowStartTime=$starttime


Use from the command line:

$ MythDataGrabber --filename=1000_20101010101010.mpg --DBHostName=localhost --DBName=mythconverg --DBUserName=mythtv --DBPassword=mythtv --output=/home/myfile.txt

rm ./DBOut

Code

This script may be used for any purpose to obtain information from the database


PythonIcon.png mythdatagrabber.py

#! /usr/bin/python
# requires libmyth-python python-lxml
import sys, os


#########################################
#Displays author and version information
def version():
    print """Written by Mike Szczys and Adam Outler
 For support, please visit: http://forum.xbmc.org/showthread.php?t=65644
 This file was written for the mythicalLibrarian project, and is
 licensed under the Apache License which requires a notification to
 outleradam (at) hotmail.com as a formality before any derrivative
 work.  We just want to hear about your project.
------------------------------------------------------------------
Version 0.1
 %s  utilizes mythtv python bindings to obtain information
about a recording and will print the information to a file.
""" % os.path.basename(sys.argv[0])
    return 0 


############################
#Displays usage information
def help():
    name = os.path.basename(sys.argv[0])
    print """ %s is designed to pull data from MythTV python bindings.

Usage:
%s --filename=file.ext : returns information to a file
   --DBHostName        : sets the DB Host, default: localhost
   --DBName            : sets the DB Name, default: mythconverg
   --DBUserName        : sets the User Name, default: mythtv
   --DBPassword        : sets the Password, default: mythtv
   --DBPin             : sets the Pin, default: 0
   --writeFile         : don't display output, write to ./showdata.txt
   --output=file.txt   : sets the output, default: ./showData.txt
   --version|-v|-ver   : displays version information
example:
$ %s --filename=1000_20101010101010.mpg --DBHostName=localhost --DBName=mythconverg --DBUserName=mythtv --DBPassword=mythtv --writeFile --output=/home/myfile.txt
""" % (name, name, name)
    return 0

################################
#Help message for invalid files
def invalidFile():
    print """target is not valid.  Please choose a valid target.
usage: %s --filename=""" % os.path.basename(sys.argv[0])
    help()
    return 0

# Setup default database information
dbInfo = {
    "DBHostName"  : "localhost",
    "DBName"      : "mythconverg",
    "DBUserName"  : "mythtv",
    "DBPassword"  : "mythtv",
    "DBPin"       : "0"
    }

# Setup other default option information
options = {
    "ToFile"      : "False",
    "output"      : "./showData.txt",
    "filename"    : "",
    "Diagnostic"  : "False"
    }  

# A list of valid command line options (anything with an = sign) and flags
validOptions = ['--DBHostName','--DBName','--DBUserName','--DBPassword', '--filename', '--output', '--DBPin', '--Diagnostic']
validVersionFlags = ['--version','-v','-ver']
validHelpFlags = ['--help','-?','-h']
validNoDisplayFlags = ['--writeFile','-w'] 


###############################
#Handle Command Line Arguments
# If there were no arguments
if len(sys.argv) < 2:
    print "ERROR: Filename must be passed as an argument"
    print
    help()
    print sys.argv[0]
    print __file__
    sys.exit(1)

#If the first argument is not a flag, treat it as the filename
if not sys.argv[1].startswith('-'):
    options['filename'] = os.path.basename(sys.argv[1])
    # Make arg list without script name and filename
    myArgs = sys.argv[2:]
else:
    # Make arg list without script name
    myArgs = sys.argv[1:]  

# Parse through the Arguments
if len(myArgs) > 0:
    for arg in myArgs:

        # Test to see if this is an option flag
        if '=' in arg and arg.split('=')[0] in validOptions:
            #This is a valid option, do something with it

            # Testing to see if it's database login info
            if arg.split('=')[0][2:] in dbInfo:
                # It's a DB login item, save it in dbInfo
                dbInfo[arg.split('=')[0][2:]] = arg.split('=')[1].replace('"','')  

            # If it's not, it must be a misc option
            elif arg.split('=')[0][2:] in options:
                #It is in the options dictionary, save it
                options[arg.split('=')[0][2:]] = arg.split('=')[1].replace('"','') 

            # If it wasn't either, then we've got problems
            else:
                print "ERROR: Option flag was valid but something went wrong trying to use" + arg
                sys.exit(1) 

        # Test to see if this is a version flag
        elif arg in validVersionFlags:
            version()
            sys.exit(0) 

        # Test to see if this is a help flag
        elif arg in validHelpFlags:
            help()
            sys.exit(0) 

        # Test to see if this is a write to file flag
        elif arg in validNoDisplayFlags:
            options['ToFile'] = 'True'

        # this is an unacceptable argument, raise an exception
        else:
            print "ERROR: Invalid command line argument: " + arg
            help()
            sys.exit(1)

# Stop execution if no filename has been set yet
if 'filename' not in options:
    #No filename has been passed
    print "ERROR: No filename specified"
    help()
    sys.exit(1) 


######################################
#Function: readMysqlTxt
#Arguments: None
#Returns: extracted login information
def readMysqlTxt():
    #Read database settings from ~/.mythtv/mysql.txt
    mysqlTXT = os.path.expanduser('~') + "/.mythtv/mysql.txt" 

    dbdata = {}
    for line in open(mysqlTXT,'r'):
        if line.startswith('#'):
            continue
        if '=' in line:
            o,v = line.strip().split('=')
            dbdata[o.strip()] = v.strip()
    return dbdata


#########################
#Get connect to database
print 'Establishing database connection'
from MythTV import MythDB
try:
    # Defaults or args
    db = MythDB(**dbInfo) 
except: 
    try:
        # mythtv preconfigured options
        print 'Failed: attempting to use system default configuration'
        db = MythDB(DBPin=dbInfo['DBPin']) 
    except:
        try:
            # read from the mysql.txt
            print 'Failed: attempting to read from default mythtv file'
            db = MythDB(readMysqlTxt() , DBPin=dbInfo['DBPin']) 
        except: 
            print 'Failed: Please specify database information manually'
            print 'DB = Null'
            sys.exit(' See --help for more information.')


##########################
#For Diagnostics purposes
if options['Diagnostic'] == 'True':
     print "Connected to:", db.gethostname()
     print "Db Identified as:",  db.ident
     print "Diagnostics passed."
     sys.exit(0)


#####################################
#GatherInformation from the Database
# search for a recording
try:
    rec = db.searchRecorded(basename=options['filename']).next()
except StopIteration:
    raise Exception('Recording Not Found')

# set comskip data
try:
    markupstart,markupstop = zip(*rec.markup.getskiplist())
except:
    print "No comskip information found."
    markupstart,markupstop='',''


#####################
#Function: writeData
#Arguments: None
#Returns: extracted login information
def writeData():
    # loop through Recorded items
    for x in rec.items():
        f.write('%s = "%s"\n' % x)

    # loop through comm-start points
    for i,data in enumerate(markupstart):
        f.write('startdata[%s] = "%s"\n' % (i, data))

    # loop through comm-end points
    for i,data in enumerate(markupstop):
        f.write('stopdata[%s] = "%s"\n' % (i, data))

    # grab guide data provider
    with db as cursor:
        # set cursor on xmltvgrabber
        cursor.execute("SELECT xmltvgrabber FROM videosource")
        # pull the data
        res = cursor.fetchone()
        # write the data if any
        if res is not None:
            f.write('xmltvgrabber = "%s"\n' % res[0].strip())
    # verify valid data was written
    if rec.chanid != '':
        print "Operation complete"


######################
#Control Data output
f = None
try:
    if options['ToFile'] == 'True':
        # Open file defined in options
        f = open(options['output'], 'w')
        # run writeData function
        writeData()
    else:
        # write to screen
        f = sys.stdout
        # run writeData function
        writeData()

#if the file failed to write
except:
    print "Write Failed, attempting to display data."
    # change to stdout
    f = sys.stdout
    writeData()    

finally:
    # close out the file/stdout
    if f is not None:
        if f.fileno() != 1:
            f.close()