XBMC Metadata .nfo generation

This commit is contained in:
Ruud
2011-09-14 08:19:58 +02:00
parent fcce56c083
commit a9d2cc10a3
11 changed files with 89 additions and 173 deletions
+2 -8
View File
@@ -42,17 +42,11 @@ class FileManager(Plugin):
if not dest: # to Cache if not dest: # to Cache
dest = os.path.join(Env.get('cache_dir'), '%s.%s' % (md5(url), getExt(url))) dest = os.path.join(Env.get('cache_dir'), '%s.%s' % (md5(url), getExt(url)))
if overwrite or not os.path.exists(dest): if overwrite or not os.path.isfile(dest):
log.debug('Writing file to: %s' % dest) self.createFile(dest, file)
output = open(dest, 'wb')
output.write(file)
output.close()
else:
log.debug('File already exists: %s' % dest)
return dest return dest
def add(self, path = '', part = 1, type = (), available = 1, properties = {}): def add(self, path = '', part = 1, type = (), available = 1, properties = {}):
db = get_session() db = get_session()
+17 -3
View File
@@ -2,14 +2,15 @@ from couchpotato import get_session
from couchpotato.core.event import addEvent, fireEventAsync, fireEvent from couchpotato.core.event import addEvent, fireEventAsync, fireEvent
from couchpotato.core.logger import CPLog from couchpotato.core.logger import CPLog
from couchpotato.core.plugins.base import Plugin from couchpotato.core.plugins.base import Plugin
from couchpotato.core.settings.model import Library, LibraryTitle, File from couchpotato.core.settings.model import Library, LibraryTitle, File, \
LibraryGenre
import traceback import traceback
log = CPLog(__name__) log = CPLog(__name__)
class LibraryPlugin(Plugin): class LibraryPlugin(Plugin):
default_dict = {'titles': {}, 'files':{}, 'info':{}} default_dict = {'titles': {}, 'files':{}, 'info':{}, 'genres':{}}
def __init__(self): def __init__(self):
addEvent('library.add', self.add) addEvent('library.add', self.add)
@@ -77,7 +78,6 @@ class LibraryPlugin(Plugin):
db.commit() db.commit()
titles = info.get('titles', []) titles = info.get('titles', [])
log.debug('Adding titles: %s' % titles) log.debug('Adding titles: %s' % titles)
for title in titles: for title in titles:
t = LibraryTitle( t = LibraryTitle(
@@ -88,6 +88,20 @@ class LibraryPlugin(Plugin):
db.commit() db.commit()
# Genres
[db.delete(genre) for genre in library.genres]
db.commit()
genres = info.get('genres', [])
log.debug('Adding genres: %s' % genres)
for genre in genres:
g = LibraryGenre(
name = genre
)
library.genres.append(g)
db.commit()
# Files # Files
images = info.get('images', []) images = info.get('images', [])
for type in images: for type in images:
+1 -3
View File
@@ -8,9 +8,7 @@ log = CPLog(__name__)
class MetaData(Plugin): class MetaData(Plugin):
def __init__(self): def __init__(self):
addEvent('renaming.after', self.add) addEvent('renamer.after', self.add)
addEvent('app.load', self.add)
def add(self, data = {}): def add(self, data = {}):
log.info('Getting meta data') log.info('Getting meta data')
@@ -77,11 +77,6 @@ config = [{
'label': 'Trailer naming', 'label': 'Trailer naming',
'default': '<filename>-trailer.<ext>', 'default': '<filename>-trailer.<ext>',
}, },
{
'name': 'backdrop_name',
'label': 'Backdrop naming',
'default': '<filename>-backdrop.<ext>',
}
], ],
}, },
], ],
+1 -2
View File
@@ -119,14 +119,13 @@ class Renamer(Plugin):
final_folder_name = self.doReplace(folder_name, replacements) final_folder_name = self.doReplace(folder_name, replacements)
final_file_name = self.doReplace(file_name, replacements) final_file_name = self.doReplace(file_name, replacements)
replacements['filename'] = final_file_name[:-(len(getExt(final_file_name)) + 1)] replacements['filename'] = final_file_name[:-(len(getExt(final_file_name)) + 1)]
group['filename'] = replacements['filename']
# Meta naming # Meta naming
if file_type is 'trailer': if file_type is 'trailer':
final_file_name = self.doReplace(trailer_name, replacements) final_file_name = self.doReplace(trailer_name, replacements)
elif file_type is 'nfo': elif file_type is 'nfo':
final_file_name = self.doReplace(nfo_name, replacements) final_file_name = self.doReplace(nfo_name, replacements)
elif file_type is 'backdrop':
final_file_name = self.doReplace(backdrop_name, replacements)
# Seperator replace # Seperator replace
if separator: if separator:
+1 -1
View File
@@ -194,7 +194,7 @@ class Scanner(Plugin):
'subtitle_extra': self.getSubtitlesExtras(group['unsorted_files']), 'subtitle_extra': self.getSubtitlesExtras(group['unsorted_files']),
'nfo': self.getNfo(group['unsorted_files']), 'nfo': self.getNfo(group['unsorted_files']),
'trailer': self.getTrailers(group['unsorted_files']), 'trailer': self.getTrailers(group['unsorted_files']),
'backdrop': images['backdrop'], #'backdrop': images['backdrop'],
'leftover': set(group['unsorted_files']), 'leftover': set(group['unsorted_files']),
} }
+2 -2
View File
@@ -1,4 +1,4 @@
from couchpotato.core.event import addEvent from couchpotato.core.event import addEvent, fireEvent
from couchpotato.core.logger import CPLog from couchpotato.core.logger import CPLog
from couchpotato.core.plugins.base import Plugin from couchpotato.core.plugins.base import Plugin
@@ -17,7 +17,7 @@ class MetaDataBase(Plugin):
log.info('Creating %s metadata.' % self.getName()) log.info('Creating %s metadata.' % self.getName())
root = self.getRootName() root = self.getRootName(release)
for type in ['nfo', 'thumbnail', 'fanart']: for type in ['nfo', 'thumbnail', 'fanart']:
try: try:
+33 -142
View File
@@ -1,15 +1,14 @@
from couchpotato.core.helpers.encoding import toUnicode
from couchpotato.core.providers.metadata.base import MetaDataBase from couchpotato.core.providers.metadata.base import MetaDataBase
from xml.etree.ElementTree import Element, SubElement, tostring from xml.etree.ElementTree import Element, SubElement, tostring
import os
import re import re
import xml.dom.minidom import xml.dom.minidom
class XBMC(MetaDataBase): class XBMC(MetaDataBase):
def getRootName(self, data = {}): def getRootName(self, data = {}):
return os.path.join(data['destination_dir'], data['filename'])
return '/Users/ruud/Downloads/Test/Transformers'
def getFanartName(self, root): def getFanartName(self, root):
return '%s-fanart.jpg' % root return '%s-fanart.jpg' % root
@@ -23,8 +22,30 @@ class XBMC(MetaDataBase):
def getNfo(self, data): def getNfo(self, data):
nfoxml = Element('movie') nfoxml = Element('movie')
types = ['title', 'rating', 'year', 'votes', 'rating', 'mpaa', 'originaltitle:original_title', 'outline:overview', 'premiered:released', 'id:imdb_id'] types = ['rating', 'year', 'votes', 'rating', 'mpaa', 'originaltitle:original_title', 'outline:plot', 'premiered:released']
# Title
try:
el = SubElement(nfoxml, 'title')
el.text = toUnicode(data['library']['titles'][0]['title'])
except:
pass
# IMDB id
try:
el = SubElement(nfoxml, 'id')
el.text = toUnicode(data['library']['identifier'])
except:
pass
# Runtime
try:
runtime = SubElement(nfoxml, 'runtime')
runtime.text = '%s min' % data['library']['runtime']
except:
pass
# Other values
for type in types: for type in types:
if ':' in type: if ':' in type:
@@ -33,20 +54,17 @@ class XBMC(MetaDataBase):
name = type name = type
try: try:
el = SubElement(nfoxml, name) if data['library'].get(type):
el.text = data.get(type, '') el = SubElement(nfoxml, name)
el.text = toUnicode(data['library'].get(type, ''))
except: except:
pass pass
#for genre in self.get('genres'): # Genre
# genres = SubElement(nfoxml, 'genre') for genre in data['library'].get('genres', []):
# genres.text = genre genres = SubElement(nfoxml, 'genre')
genres.text = genre.get('name')
try:
runtime = SubElement(nfoxml, 'runtime')
runtime.text = data.get('runtime') + " min"
except:
pass
# Clean up the xml and return it # Clean up the xml and return it
nfoxml = xml.dom.minidom.parseString(tostring(nfoxml)) nfoxml = xml.dom.minidom.parseString(tostring(nfoxml))
@@ -55,130 +73,3 @@ class XBMC(MetaDataBase):
xml_string = text_re.sub('>\g<1></', xml_string) xml_string = text_re.sub('>\g<1></', xml_string)
return xml_string.encode('utf-8') return xml_string.encode('utf-8')
"""
def _get_fanart(self, min_height, min_width):
''' Fetches the fanart for the specified imdb_id and saves it to dir.
Arguments
min_height/width: Sets lowest acceptable resolution fanart. 0 means
disregard. If no fanart available at specified resolution or greater, then
we disregard.
'''
images = [image['image'] for image in self.tmdb_data['backdrops'] if image['image'].get('size') == 'original']
if len(images) == 0:
return
return self._get_image(images, min_height, min_width)
def get_fanart_url(self, min_height, min_width):
return self._get_fanart(min_height, min_width)['url']
def write_fanart(self, filename_root, path, min_height, min_width):
fanart_url = self.get_fanart_url(min_height, min_width)
#fetch and write to disk
dest = os.path.join(path, filename_root)
try:
f = open(dest, 'wb')
except:
raise IOError("Can't open for writing: %s" % dest)
response = urllib2.urlopen(fanart_url)
f.write(response.read())
f.close()
return True
def _get_poster(self, min_height, min_width):
''' Fetches the poster for the specified imdb_id and saves it to dir.
Arguments
min_height/width: Sets lowest acceptable resolution poster. 0 means
disregard. If no poster available at specified resolution or greater, then
we disregard.
'''
images = [image['image'] for image in self.tmdb_data['posters'] if image['image'].get('size') == 'original']
if len(images) == 0:
return
return self._get_image(images, min_height, min_width)
def get_poster_url(self, min_height, min_width):
return self._get_poster(min_height, min_width)['url']
def write_poster(self, filename_root, path, min_height, min_width):
poster_url = self.get_poster_url(min_height, min_width)
dest = os.path.join(path, filename_root)
try:
f = open(dest, 'wb')
except:
raise IOError("Can't open for writing: %s" % dest)
response = urllib2.urlopen(poster_url)
f.write(response.read())
f.close()
return True
def _get_tmdb_imdb(self):
url = "http://api.themoviedb.org/2.1/Movie.imdbLookup/en/json/%s/%s" % (__tmdb_apikey__, self.imdbid)
count = 0
while 1:
count += 1
response = urllib2.urlopen(url)
json_string = response.read()
try:
tmdb_data = json.loads(json_string)[0]
return tmdb_data
except ValueError, e:
if count < 3:
continue
else:
raise ApiError("Invalid JSON: %s: %s" % (e, json_string))
except:
ApiError("JSON error with: %s" % json_string)
def _get_image(self, image_list, min_height, min_width):
#Select image
images = []
for image in image_list:
if not min_height or min_width:
images.append(image)
break
elif min_height and not min_width:
if image['height'] >= min_height:
images.append(image)
break
elif min_width and not min_height:
if image['width'] >= min_width:
images.append(image)
break
elif min_width and min_height:
if image['width'] >= min_width and image['height'] >= min_height:
images.append(image)
break
#No image meets our resolution requirements, so disregard those requirements
if len(images) == 0 and min_height or min_width:
images.append(image_list[0])
return images[0]
if __name__ == "__main__":
import sys
try:
id = sys.argv[1]
except:
id = 'tt0111161'
x = MetaGen(id)
x.write_nfo("movie.nfo")
try:
x.write_fanart("fanart.jpg", ".", 0, 0)
except: pass
try:
x.write_poster("movie.tbn", ".", 0, 0)
except: pass
"""
@@ -92,7 +92,7 @@ class TheMovieDb(MovieProvider):
def getInfo(self, identifier = None): def getInfo(self, identifier = None):
cache_key = 'tmdb.cache.%s' % identifier cache_key = 'tmdb.cache.%s' % identifier
result = self.getCache(cache_key) result = None #self.getCache(cache_key)
if not result: if not result:
result = {} result = {}
@@ -112,27 +112,33 @@ class TheMovieDb(MovieProvider):
def parseMovie(self, movie): def parseMovie(self, movie):
year = str(movie.get('released', 'none'))[:4]
# Poster url # Poster url
poster = self.getImage(movie, type = 'poster') poster = self.getImage(movie, type = 'poster')
backdrop = self.getImage(movie, type = 'backdrop') backdrop = self.getImage(movie, type = 'backdrop')
# Genres
genres = self.getCategory(movie, 'genre')
# 1900 is the same as None # 1900 is the same as None
year = str(movie.get('released', 'none'))[:4]
if year == '1900' or year.lower() == 'none': if year == '1900' or year.lower() == 'none':
year = None year = None
movie_data = { movie_data = {
'id': int(movie.get('id', 0)), 'id': int(movie.get('id', 0)),
'titles': [toUnicode(movie.get('name'))], 'titles': [toUnicode(movie.get('name'))],
'original_title': movie.get('original_name'),
'images': { 'images': {
'posters': [poster], 'posters': [poster],
'backdrops': [backdrop], 'backdrops': [backdrop],
}, },
'imdb': movie.get('imdb_id'), 'imdb': movie.get('imdb_id'),
'runtime': movie.get('runtime'),
'released': movie.get('released'),
'year': year, 'year': year,
'plot': movie.get('overview', ''), 'plot': movie.get('overview', ''),
'tagline': '', 'tagline': '',
'genres': genres,
} }
# Add alternative names # Add alternative names
@@ -153,6 +159,19 @@ class TheMovieDb(MovieProvider):
return image return image
def getCategory(self, movie, type = 'genre'):
cats = movie.get('categories', {}).get(type)
categories = []
for category in cats:
try:
categories.append(category)
except:
pass
return categories
def isDisabled(self): def isDisabled(self):
if self.conf('api_key') == '': if self.conf('api_key') == '':
log.error('No API key provided.') log.error('No API key provided.')
+9 -3
View File
@@ -44,12 +44,10 @@ class Library(Entity):
status = ManyToOne('Status') status = ManyToOne('Status')
movies = OneToMany('Movie') movies = OneToMany('Movie')
titles = OneToMany('LibraryTitle') titles = OneToMany('LibraryTitle')
genres = ManyToMany('LibraryGenre')
files = ManyToMany('File') files = ManyToMany('File')
info = OneToMany('LibraryInfo') info = OneToMany('LibraryInfo')
def title(self):
return self.titles[0]['title']
class LibraryInfo(Entity): class LibraryInfo(Entity):
"""""" """"""
@@ -71,6 +69,14 @@ class LibraryTitle(Entity):
libraries = ManyToOne('Library') libraries = ManyToOne('Library')
class LibraryGenre(Entity):
""""""
name = Field(Unicode)
libraries = ManyToMany('Library')
class Language(Entity): class Language(Entity):
"""""" """"""
+1 -1
View File
@@ -350,7 +350,7 @@ class MovieDb:
etree = XmlHandler(url).getEt() etree = XmlHandler(url).getEt()
lookup_results = SearchResults() lookup_results = SearchResults()
for cur_lookup in etree.find("movies").findall("movie"): for cur_lookup in etree.find("movies").findall("movie"):
cur_movie = self._parseSearchResults(cur_lookup) cur_movie = self._parseMovie(cur_lookup)
lookup_results.append(cur_movie) lookup_results.append(cur_movie)
return lookup_results return lookup_results