Ticket #6680: mythvidexport.2.py

File mythvidexport.2.py, 8.9 KB (added by Raymond Wagner <raymond@…>, 15 years ago)
Line 
1#!/usr/local/bin/python
2from MythTV import MythDB, MythLog, MythTV, MythVideo, Program, Job
3from socket import gethostname
4import sys, getopt, re, os, time, logging, pprint
5
6#Usage: mythvidexport.py <--chanid <channel id>> <--starttime <start time>> [options]
7#               --format <see directory/file name options>
8#       moves a single file over to MythVideo with optional directory format, format is discarded after use
9
10#Usage: mythvidexport.py <job id>
11#               WARNING: for internal use by job queue only!
12#       moves a single file, grabbing necessary information from job queue table
13
14#Usage: mythvidexport.py <options>
15#               --setformat <see directory/file name options>
16#                       stored directory format in database for future use
17#               --help
18#               --helpformat
19#                       lengthy discription of directory formatting
20
21
22class VIDEO:
23        mythdb = None
24        dbconn = None
25        job = None
26        jobhost = None
27        chanid = None
28        rtime = None
29        source = None
30        srchost = None
31        srcdb = None
32        dest = None
33        desthost = None
34        destdb = None
35        prog = None
36        fmt = None
37        log = None
38        epstr = None
39
40        season= None
41        episode = None
42        viddata = {}
43        cast = None
44        genre = None
45        country = None
46
47        def __init__(self, *inp):
48                if len(inp) == 1:
49                        self.job = Job(inp[0]);
50                        self.chanid = self.job.chanid
51                        self.rtime = "%04d%02d%02d%02d%02d%02d" % self.job.starttime.timetuple()[0:6]
52                        self.jobhost = self.job.host
53                        self.job.setStatus(3)
54                elif len(inp) == 2:
55                        self.chanid = inp[0]
56                        self.rtime = inp[1]
57                else:
58                        sys.exit(2)
59                self.get_source()
60                self.log = MythLog(logging.CRITICAL, '#%(levelname)s - %(message)s', 'MythTV')
61
62        def dbconnect(self):
63                self.mythdb = MythDB()
64                self.dbconn = self.mythdb.db
65
66        def get_source(self):
67                if not self.dbconn:
68                        self.dbconnect()
69                if not self.jobhost:
70                        self.jobhost = gethostname()
71
72                mythinst = MythTV()
73                self.prog = mythinst.getRecording(self.chanid,int(self.rtime))
74
75                self.srcdb = self.prog.filename
76                self.srchost = self.prog.hostname
77
78                self.source = mythinst.getCheckfile(self.prog)
79
80        def find_ttvdb(self):
81                if os.access('/usr/local/share/mythtv/mythvideo/scripts/ttvdb.py',os.F_OK):
82                        self.ttvdb = '/usr/local/share/mythtv/mythvideo/scripts/ttvdb.py'
83                elif os.access('/usr/share/mythtv/mythvideo/scripts/ttvdb.py',os.F_OK):
84                        self.ttvdb = '/usr/local/share/mythtv/mythvideo/scripts/ttvdb.py'
85                else:
86                        self.log.Msg(logging.CRITICAL, "Could not find ttvdb.py")
87                        self.exit(2)
88
89        def get_meta(self, use_ttvdb):
90                regex = re.compile('S(?P<season>[0-9]*)E(?P<episode>[0-9]*)')
91                match = None
92                if use_ttvdb == 0:
93                        match = regex.search(self.epstr)
94                elif use_ttvdb in (1,2):
95                        self.find_ttvdb()
96                        fp = os.popen("%s -N \"%s\" \"%s\"" % (self.ttvdb,self.prog.title,self.prog.subtitle),"r")
97                        match = regex.search(fp.read())
98                        fp.close()
99                if match is None:
100                        if self.job:
101                                self.job.setComment("TTVDB.py failed to get season/episode numbers")
102                                self.job.setStatus(304)
103                                self.log.Msg(logging.CRITICAL, "TTVDB.py failed to get season/episode numbers")
104                        else:
105                                print("TTVDB.py failed to get season/episode numbers")
106                        sys.exit(2)
107                self.season = int(match.group('season'))
108                self.episode = int(match.group('episode'))
109
110                if use_ttvdb == 2:
111                        print("calling '%s -mD '%s' %d %d'" % (self.ttvdb,self.prog.title,self.season,self.episode))
112                        fp = os.popen("%s -mD '%s' %d %d" % (self.ttvdb,self.prog.title,self.season,self.episode))
113                        time.sleep(2)
114                        res = fp.read()
115                        fp.close()
116                        ttvdbdat = {}
117                        if len(res) == 0:
118                                self.get_metadata(1)
119                                return
120                        for point in res.split('\n')[:-1]:
121                                key,dat = point.split(':',1)
122                                ttvdbdat[key] = dat
123                        self.viddata['director'] = ttvdbdat['Director']
124                        self.viddata['plot'] = ttvdbdat['Plot']
125                        self.viddata['year'] = ttvdbdat['Year']
126                        self.viddata['length'] = ttvdbdat['Runtime']
127                        self.viddata['userrating'] = ttvdbdat['UserRating']
128                        self.cast = tuple(ttvdbdat['Cast'].split(', '))
129                        self.genre = tuple(ttvdbdat['Genres'].split(', '))
130                        self.country = ()
131                else:
132                        self.viddata['director'] = self.mythdb.getCast(self.chanid, int(self.rtime), roles='director')
133                        if len(self.viddata['director']) == 0:
134                                self.viddata['director'] = 'NULL'
135                        else:
136                                self.viddata['director'] = self.viddata['director'][0]
137                        self.viddata['plot'] = self.prog.description
138                        self.viddata['year'] = self.prog.airdate.split('-')[0]
139                        self.viddata['length'] = str(int((self.prog.recendts-self.prog.recstartts).seconds/60))
140                        self.cast = self.mythdb.getCast(self.chanid, int(self.rtime), roles=('actor','guest_star','host','commentator','guest'))
141                        self.genre = ()
142                        self.country = ()
143
144                self.viddata['showlevel'] = 1
145                self.viddata['rating'] = 'NR'
146                self.viddata['inetref'] = '00000000'
147                self.viddata['coverfile'] = 'No Cover'
148
149        def get_dest(self):
150                #process self.fmt and generate self.dest
151                #not programmed yet... just use my own naming scheme
152                ext = self.source[self.source.rfind('.'):]
153                #replace with sequence of str-replace for the formatted destination
154                subpath = "TV/%s/Season %d/%dx%02d - %s%s" % (self.prog.title,self.season,self.season,self.episode,self.prog.subtitle,ext)
155
156                self.desthost = self.jobhost
157                cursor = self.dbconn.cursor()
158                reslen = cursor.execute("SELECT dirname FROM storagegroup WHERE hostname='%s' and groupname='Videos'" % self.desthost)
159                if reslen:
160                        self.dest = cursor.fetchone()[0]+'/'+subpath
161                        self.destdb = subpath
162                else:
163                        self.dest = self.mythdb.getSetting("VideoStartupDir",hostname=self.jobhost)+'/'+subpath
164                        self.destdb = self.dest
165
166
167                tmppath = self.dest[0:self.dest.rfind('/')]
168                if not os.access(tmppath,os.F_OK):
169                        os.makedirs(tmppath)
170
171        def set_fmt(self, fmt):
172                self.fmt = fmt
173
174        def get_fmt(self):
175                self.fmt = self.mythdb.getSetting('mythvideo.exportfmt')
176
177        def copy(self):
178                cursor = None
179                fp = None
180                srcsize = None
181                dtime = None
182                if self.fmt is None:
183                        self.get_fmt()
184                self.get_dest()
185                if self.desthost != self.jobhost:
186                        if self.job:
187                                self.job.setComment("Job must be run on destination host")
188                                self.log.Msg(logging.CRITICAL, 'MythVidExport failed - must be run on destination host')
189                                self.job.setStatus(304)
190                        else:
191                                print("ERROR: job must be run on destionation host")
192                        sys.exit(2)
193
194                stime = time.time()
195                print("Copying %s to %s..." % (self.source,self.dest))
196                fp = os.popen("cp \"%s\" \"%s\"" % (self.source,self.dest))
197#               if self.srchost == self.jobhost:
198#                       fp = os.popen("cp '%s' '%s'" % (self.source,self.dest))
199#               else:
200#                       fp = os.popen("scp '%s:%s' '%s'" % (self.srchost, self.source, self.dest))
201                srcsize = self.prog.filesize
202                destsize = [0,0,0,0,0,0,0,0,0,0]
203                if self.job:
204                        self.job.setStatus(4)
205                while srcsize > destsize[9]:
206                        time.sleep(4)
207                        destsize.append(os.stat(self.dest)[6])
208                        rem = srcsize-destsize[10]
209                        if destsize[0]:
210                                dtime = 40
211                        else:
212                                dtime = int(time.time()-stime)
213                        rate = (destsize[10]-destsize.pop(0))/dtime
214                        remt = rem/rate
215                        if self.job:
216                                self.job.setComment("%02d%% complete - %s seconds remaining" % (destsize[9]*100/srcsize, remt))
217                fp.close()
218                if self.job:
219                        self.job.setComment("Complete - %d seconds elapsed" % (int(time.time()-stime)))
220                        self.job.setStatus(256)
221
222
223        def write_meta(self):
224                mythvid = MythVideo()
225                mythtv = MythTV()
226                pp = pprint.PrettyPrinter(indent=4)
227                self.viddata['title'] = '%dx%02d - %s' % (self.season, self.episode, self.prog.subtitle)
228                self.viddata['filename'] = self.destdb
229                self.viddata['host'] = self.desthost
230
231
232                pp.pprint(self.viddata)
233                intid = mythvid.getMetadataId(self.destdb)
234                if intid:
235                        mythvid.setMetadata(self.viddata,intid)
236                else:
237                        intid = mythvid.setMetadata(self.viddata)
238                print("Metadata written to intid %d" % intid)
239                pp.pprint(self.viddata)
240
241                print("With cast:")
242                pp.pprint(self.cast)
243                for name in self.cast:
244                        mythvid.setCast(name, intid)
245                print("With genre:")
246                pp.pprint(self.genre)
247#               for genre in self.genre:
248#                       mythvid.setGenre(genre, intid)
249
250                if self.job:
251                        self.job.setStatus(272)
252
253def usage():
254        print("bleg")
255
256def usage_format():
257        print("more bleg")
258
259def main():
260        format = None
261        jobid = None
262        chanid = None
263        rtime = None
264        episode = None
265        ttvdb = 1
266        skip = False
267        try:
268                opts, args = getopt.getopt(sys.argv[1:], "hf", ["help","helpformat","format=","chanid=","starttime=","episode=","ttvdb","skip"])
269        except getopt.GetoptError, err:
270                print(str(err))
271                usage()
272                sys.exit(2)
273        for opt, arg in opts:
274                if opt in ("-h", "--help"):
275                        usage()
276                        sys.exit()
277                elif opt in ('-f', '--helpformat'):
278                        usage_format()
279                        sys.exit()
280                elif opt == '--format':
281                        format = arg
282                elif opt == '--chanid':
283                        chanid = int(arg)
284                elif opt == '--starttime':
285                        rtime = int(arg)
286                elif opt == '--episode':
287                        ttvdb = 0
288                        episode = arg
289                elif opt == '--ttvdb':
290                        ttvdb = 2
291                elif opt == '--skip':
292                        skip = True
293               
294        if len(args):
295                jobid = int(args[0])
296
297        if chanid and rtime:
298                export = VIDEO(chanid,rtime)
299        elif jobid:
300                export = VIDEO(jobid)
301        elif format:
302                # store format to database
303                sys.exit()
304        else:
305                usage()
306                sys.exit(2)
307
308        if format:
309                export.set_fmt(format)
310        if episode:
311                export.epstr = episode
312        export.get_meta(ttvdb)
313        if skip:
314                export.get_dest()
315        else:
316                export.copy()
317        export.write_meta()
318
319if __name__ == "__main__":
320        main()