Document togo_path; change defaults of "blank" to "None", for consistency.
[pyTivo/TheBayer.git] / metadata.py
blob28af7b8e4a27e532078d2d231ee283b0b81d199e
1 #!/usr/bin/env python
3 import os
4 import subprocess
5 from datetime import datetime
6 from xml.dom import minidom
8 from lrucache import LRUCache
10 import config
12 # Something to strip
13 TRIBUNE_CR = ' Copyright Tribune Media Services, Inc.'
15 tivo_cache = LRUCache(50)
17 def tag_data(element, tag):
18 for name in tag.split('/'):
19 new_element = element.getElementsByTagName(name)
20 if not new_element:
21 return ''
22 element = new_element[0]
23 if not element.firstChild:
24 return ''
25 return element.firstChild.data
27 def _vtag_data(element, tag):
28 for name in tag.split('/'):
29 new_element = element.getElementsByTagName(name)
30 if not new_element:
31 return []
32 element = new_element[0]
33 elements = element.getElementsByTagName('element')
34 return [x.firstChild.data for x in elements if x.firstChild]
36 def _tag_value(element, tag):
37 item = element.getElementsByTagName(tag)
38 if item:
39 value = item[0].attributes['value'].value
40 name = item[0].firstChild.data
41 return name[0] + value[0]
43 def from_text(full_path):
44 metadata = {}
45 path, name = os.path.split(full_path)
46 for metafile in [os.path.join(path, 'default.txt'), full_path + '.txt',
47 os.path.join(path, '.meta', name) + '.txt']:
48 if os.path.exists(metafile):
49 for line in file(metafile):
50 if line.strip().startswith('#') or not ':' in line:
51 continue
52 key, value = [x.strip() for x in line.split(':', 1)]
53 if key.startswith('v'):
54 if key in metadata:
55 metadata[key].append(value)
56 else:
57 metadata[key] = [value]
58 else:
59 metadata[key] = value
60 return metadata
62 def basic(full_path):
63 base_path, title = os.path.split(full_path)
64 mtime = os.stat(full_path).st_mtime
65 if (mtime < 0):
66 mtime = 0
67 originalAirDate = datetime.fromtimestamp(mtime)
69 metadata = {'title': '.'.join(title.split('.')[:-1]),
70 'originalAirDate': originalAirDate.isoformat()}
72 metadata.update(from_text(full_path))
74 return metadata
76 def from_container(xmldoc):
77 metadata = {}
79 keys = {'title': 'Title', 'episodeTitle': 'EpisodeTitle',
80 'description': 'Description', 'seriesId': 'SeriesId',
81 'episodeNumber': 'EpisodeNumber', 'tvRating': 'TvRating',
82 'displayMajorNumber': 'SourceChannel', 'callsign': 'SourceStation'}
84 details = xmldoc.getElementsByTagName('Details')[0]
86 for key in keys:
87 data = tag_data(details, keys[key])
88 if data:
89 if key == 'description':
90 data = data.replace(TRIBUNE_CR, '')
91 elif key == 'tvRating':
92 data = 'x' + data
93 elif key == 'displayMajorNumber':
94 if '-' in data:
95 data, metadata['displayMinorNumber'] = data.split('-')
96 metadata[key] = data
98 return metadata
100 def from_details(xmldoc):
101 metadata = {}
103 showing = xmldoc.getElementsByTagName('showing')[0]
104 program = showing.getElementsByTagName('program')[0]
106 items = {'description': 'program/description',
107 'title': 'program/title',
108 'episodeTitle': 'program/episodeTitle',
109 'episodeNumber': 'program/episodeNumber',
110 'seriesId': 'program/series/uniqueId',
111 'seriesTitle': 'program/series/seriesTitle',
112 'originalAirDate': 'program/originalAirDate',
113 'isEpisode': 'program/isEpisode',
114 'movieYear': 'program/movieYear',
115 'partCount': 'partCount',
116 'partIndex': 'partIndex'}
118 for item in items:
119 data = tag_data(showing, items[item])
120 if data:
121 if item == 'description':
122 data = data.replace(TRIBUNE_CR, '')
123 metadata[item] = data
125 vItems = ['vActor', 'vChoreographer', 'vDirector',
126 'vExecProducer', 'vProgramGenre', 'vGuestStar',
127 'vHost', 'vProducer', 'vWriter']
129 for item in vItems:
130 data = _vtag_data(program, item)
131 if data:
132 metadata[item] = data
134 sb = showing.getElementsByTagName('showingBits')
135 if sb:
136 metadata['showingBits'] = sb[0].attributes['value'].value
138 for tag in ['starRating', 'mpaaRating', 'colorCode']:
139 value = _tag_value(program, tag)
140 if value:
141 metadata[tag] = value
143 rating = _tag_value(showing, 'tvRating')
144 if rating:
145 metadata['tvRating'] = 'x' + rating[1]
147 return metadata
149 def from_tivo(full_path):
150 if full_path in tivo_cache:
151 return tivo_cache[full_path]
153 tdcat_path = config.get_bin('tdcat')
154 tivo_mak = config.get_server('tivo_mak')
155 if tdcat_path and tivo_mak:
156 tcmd = [tdcat_path, '-m', tivo_mak, '-2', full_path]
157 tdcat = subprocess.Popen(tcmd, stdout=subprocess.PIPE)
158 xmldoc = minidom.parse(tdcat.stdout)
159 metadata = from_details(xmldoc)
160 tivo_cache[full_path] = metadata
161 else:
162 metadata = {}
164 return metadata
166 if __name__ == '__main__':
167 import sys
168 if len(sys.argv) > 1:
169 config.init([])
170 metadata = from_tivo(sys.argv[1])
171 for key in metadata:
172 value = metadata[key]
173 if type(value) == list:
174 for item in value:
175 print '%s: %s' % (key, item.encode('utf8'))
176 else:
177 print '%s: %s' % (key, value.encode('utf8'))