mirror of
https://github.com/SickGear/SickGear.git
synced 2024-12-03 18:03:37 +00:00
Merge branch 'hotfix/0.16.16'
This commit is contained in:
commit
54a877d3e3
13 changed files with 257 additions and 247 deletions
|
@ -1,4 +1,10 @@
|
||||||
### 0.16.15 (2018-06-03 21:24:00 UTC)
|
### 0.16.16 (2018-06-09 12:13:00 UTC)
|
||||||
|
|
||||||
|
* Fix metadata mediabrowser when no actors
|
||||||
|
* Add 'vp9' and 'av1' to ignore word list
|
||||||
|
|
||||||
|
|
||||||
|
### 0.16.15 (2018-06-03 21:24:00 UTC)
|
||||||
|
|
||||||
* Change garbage_name regex
|
* Change garbage_name regex
|
||||||
|
|
||||||
|
|
|
@ -398,17 +398,17 @@ class Tvdb:
|
||||||
|
|
||||||
banners (True/False):
|
banners (True/False):
|
||||||
Retrieves the banners for a show. These are accessed
|
Retrieves the banners for a show. These are accessed
|
||||||
via the _banners key of a Show(), for example:
|
via the banners key of a Show(), for example:
|
||||||
|
|
||||||
>> Tvdb(banners=True)['scrubs']['_banners'].keys()
|
>> Tvdb(banners=True)['scrubs']['banners'].keys()
|
||||||
['fanart', 'poster', 'series', 'season']
|
['fanart', 'poster', 'series', 'season']
|
||||||
|
|
||||||
actors (True/False):
|
actors (True/False):
|
||||||
Retrieves a list of the actors for a show. These are accessed
|
Retrieves a list of the actors for a show. These are accessed
|
||||||
via the _actors key of a Show(), for example:
|
via the actors key of a Show(), for example:
|
||||||
|
|
||||||
>> t = Tvdb(actors=True)
|
>> t = Tvdb(actors=True)
|
||||||
>> t['scrubs']['_actors'][0]['name']
|
>> t['scrubs']['actors'][0]['name']
|
||||||
u'Zach Braff'
|
u'Zach Braff'
|
||||||
|
|
||||||
custom_ui (tvdb_ui.BaseUI subclass):
|
custom_ui (tvdb_ui.BaseUI subclass):
|
||||||
|
@ -524,7 +524,7 @@ class Tvdb:
|
||||||
self.config['url_actorsInfo'] = '%(base_url)sseries/%%s/actors' % self.config
|
self.config['url_actorsInfo'] = '%(base_url)sseries/%%s/actors' % self.config
|
||||||
|
|
||||||
self.config['url_seriesBanner'] = '%(base_url)sseries/%%s/images/query?keyType=%%s' % self.config
|
self.config['url_seriesBanner'] = '%(base_url)sseries/%%s/images/query?keyType=%%s' % self.config
|
||||||
self.config['url_artworkPrefix'] = 'https://thetvdb.com/banners/%s'
|
self.config['url_artworkPrefix'] = 'https://www.thetvdb.com/banners/%s'
|
||||||
|
|
||||||
def get_new_token(self):
|
def get_new_token(self):
|
||||||
token = sickbeard.THETVDB_V2_API_TOKEN.get('token', None)
|
token = sickbeard.THETVDB_V2_API_TOKEN.get('token', None)
|
||||||
|
@ -784,10 +784,10 @@ class Tvdb:
|
||||||
k, v = k.lower(), v.lower() if isinstance(v, (str, unicode)) else v
|
k, v = k.lower(), v.lower() if isinstance(v, (str, unicode)) else v
|
||||||
if k == 'filename':
|
if k == 'filename':
|
||||||
k = 'bannerpath'
|
k = 'bannerpath'
|
||||||
banners[btype][btype2][bid]['_bannerpath'] = self.config['url_artworkPrefix'] % v
|
banners[btype][btype2][bid]['bannerpath'] = self.config['url_artworkPrefix'] % v
|
||||||
elif k == 'thumbnail':
|
elif k == 'thumbnail':
|
||||||
k = 'thumbnailpath'
|
k = 'thumbnailpath'
|
||||||
banners[btype][btype2][bid]['_thumbnailpath'] = self.config['url_artworkPrefix'] % v
|
banners[btype][btype2][bid]['thumbnailpath'] = self.config['url_artworkPrefix'] % v
|
||||||
elif k == 'keytype':
|
elif k == 'keytype':
|
||||||
k = 'bannertype'
|
k = 'bannertype'
|
||||||
banners[btype][btype2][bid][k] = v
|
banners[btype][btype2][bid][k] = v
|
||||||
|
@ -799,23 +799,28 @@ class Tvdb:
|
||||||
|
|
||||||
def _parse_actors(self, sid, actor_list):
|
def _parse_actors(self, sid, actor_list):
|
||||||
|
|
||||||
cur_actors = Actors()
|
a = []
|
||||||
try:
|
try:
|
||||||
for curActorItem in actor_list:
|
for n in sorted(actor_list, key=lambda x: x['sortorder']):
|
||||||
cur_actor = Actor()
|
a.append({'character': {'id': None,
|
||||||
for k, v in curActorItem.iteritems():
|
'name': n.get('role', '').strip(),
|
||||||
k = k.lower()
|
'url': None, # not supported by tvdb
|
||||||
if None is not v:
|
'image': (None, self.config['url_artworkPrefix'] %
|
||||||
if 'image' == k:
|
n.get('image'))[any([n.get('image')])],
|
||||||
v = self.config['url_artworkPrefix'] % v
|
},
|
||||||
else:
|
'person': {'id': None, # not supported by tvdb
|
||||||
v = self._clean_data(v)
|
'name': n.get('name', '').strip(),
|
||||||
cur_actor[k] = v
|
'url': None, # not supported by tvdb
|
||||||
cur_actors.append(cur_actor)
|
'image': None, # not supported by tvdb
|
||||||
|
'birthday': None, # not supported by tvdb
|
||||||
|
'deathday': None, # not supported by tvdb
|
||||||
|
'gender': None, # not supported by tvdb
|
||||||
|
'country': None, # not supported by tvdb
|
||||||
|
},
|
||||||
|
})
|
||||||
except (StandardError, Exception):
|
except (StandardError, Exception):
|
||||||
pass
|
pass
|
||||||
|
self._set_show_data(sid, 'actors', a)
|
||||||
self._set_show_data(sid, '_actors', cur_actors)
|
|
||||||
|
|
||||||
def get_episode_data(self, epid):
|
def get_episode_data(self, epid):
|
||||||
# Parse episode information
|
# Parse episode information
|
||||||
|
@ -907,12 +912,7 @@ class Tvdb:
|
||||||
if self.config['actors_enabled']:
|
if self.config['actors_enabled']:
|
||||||
actor_data = self._getetsrc(self.config['url_actorsInfo'] % sid, language=language)
|
actor_data = self._getetsrc(self.config['url_actorsInfo'] % sid, language=language)
|
||||||
if actor_data and len(actor_data.get('data', '') or '') > 0:
|
if actor_data and len(actor_data.get('data', '') or '') > 0:
|
||||||
a = '|%s|' % '|'.join([n.get('name', '') for n in sorted(
|
|
||||||
actor_data['data'], key=lambda x: x['sortorder'])])
|
|
||||||
self._parse_actors(sid, actor_data['data'])
|
self._parse_actors(sid, actor_data['data'])
|
||||||
else:
|
|
||||||
a = '||'
|
|
||||||
self._set_show_data(sid, u'actors', a)
|
|
||||||
|
|
||||||
if get_ep_info:
|
if get_ep_info:
|
||||||
# Parse episode data
|
# Parse episode data
|
||||||
|
|
|
@ -380,7 +380,7 @@ class TvdbV1:
|
||||||
Retrieves the banners for a show. These are accessed
|
Retrieves the banners for a show. These are accessed
|
||||||
via the _banners key of a Show(), for example:
|
via the _banners key of a Show(), for example:
|
||||||
|
|
||||||
>> Tvdb(banners=True)['scrubs']['_banners'].keys()
|
>> Tvdb(banners=True)['scrubs']['banners'].keys()
|
||||||
['fanart', 'poster', 'series', 'season']
|
['fanart', 'poster', 'series', 'season']
|
||||||
|
|
||||||
actors (True/False):
|
actors (True/False):
|
||||||
|
@ -388,7 +388,7 @@ class TvdbV1:
|
||||||
via the _actors key of a Show(), for example:
|
via the _actors key of a Show(), for example:
|
||||||
|
|
||||||
>> t = Tvdb(actors=True)
|
>> t = Tvdb(actors=True)
|
||||||
>> t['scrubs']['_actors'][0]['name']
|
>> t['scrubs']['actors'][0]['name']
|
||||||
u'Zach Braff'
|
u'Zach Braff'
|
||||||
|
|
||||||
custom_ui (tvdb_ui.BaseUI subclass):
|
custom_ui (tvdb_ui.BaseUI subclass):
|
||||||
|
@ -514,7 +514,7 @@ class TvdbV1:
|
||||||
self.config['url_actorsInfo'] = u'%(base_url)s/api/%(apikey)s/series/%%s/actors.xml' % self.config
|
self.config['url_actorsInfo'] = u'%(base_url)s/api/%(apikey)s/series/%%s/actors.xml' % self.config
|
||||||
|
|
||||||
self.config['url_seriesBanner'] = u'%(base_url)s/api/%(apikey)s/series/%%s/banners.xml' % self.config
|
self.config['url_seriesBanner'] = u'%(base_url)s/api/%(apikey)s/series/%%s/banners.xml' % self.config
|
||||||
self.config['url_artworkPrefix'] = u'%(base_url)s/banners/%%s' % self.config
|
self.config['url_artworkPrefix'] = u'https://thetvdb.com/banners/%%s' % self.config
|
||||||
|
|
||||||
def log(self, msg, log_level=logger.DEBUG):
|
def log(self, msg, log_level=logger.DEBUG):
|
||||||
logger.log('TVDB_API :: %s' % (msg.replace(self.config['apikey'], '<apikey>')), log_level=log_level)
|
logger.log('TVDB_API :: %s' % (msg.replace(self.config['apikey'], '<apikey>')), log_level=log_level)
|
||||||
|
@ -699,7 +699,7 @@ class TvdbV1:
|
||||||
>> t = Tvdb(banners = True)
|
>> t = Tvdb(banners = True)
|
||||||
>> t['scrubs']['_banners'].keys()
|
>> t['scrubs']['_banners'].keys()
|
||||||
['fanart', 'poster', 'series', 'season']
|
['fanart', 'poster', 'series', 'season']
|
||||||
>> t['scrubs']['_banners']['poster']['680x1000']['35308']['_bannerpath']
|
>> t['scrubs']['_banners']['poster']['680x1000']['35308']['bannerpath']
|
||||||
u'http://thetvdb.com/banners/posters/76156-2.jpg'
|
u'http://thetvdb.com/banners/posters/76156-2.jpg'
|
||||||
>>
|
>>
|
||||||
|
|
||||||
|
@ -751,7 +751,7 @@ class TvdbV1:
|
||||||
Actors are retrieved using t['show name]['_actors'], for example:
|
Actors are retrieved using t['show name]['_actors'], for example:
|
||||||
|
|
||||||
>> t = Tvdb(actors = True)
|
>> t = Tvdb(actors = True)
|
||||||
>> actors = t['scrubs']['_actors']
|
>> actors = t['scrubs']['actors']
|
||||||
>> type(actors)
|
>> type(actors)
|
||||||
<class 'tvdb_api.Actors'>
|
<class 'tvdb_api.Actors'>
|
||||||
>> type(actors[0])
|
>> type(actors[0])
|
||||||
|
@ -771,23 +771,28 @@ class TvdbV1:
|
||||||
self.log('Getting actors for %s' % sid)
|
self.log('Getting actors for %s' % sid)
|
||||||
actors_et = self._getetsrc(self.config['url_actorsInfo'] % sid)
|
actors_et = self._getetsrc(self.config['url_actorsInfo'] % sid)
|
||||||
|
|
||||||
cur_actors = Actors()
|
a = []
|
||||||
try:
|
try:
|
||||||
for curActorItem in actors_et['actor']:
|
for n in sorted(actors_et['Actor'], key=lambda x: x['SortOrder']):
|
||||||
cur_actor = Actor()
|
a.append({'character': {'id': None,
|
||||||
for k, v in curActorItem.items():
|
'name': n.get('Role', '').strip(),
|
||||||
k = k.lower()
|
'url': None, # not supported by tvdb
|
||||||
if None is not v:
|
'image': (None, self.config['url_artworkPrefix'] %
|
||||||
if 'image' == k:
|
n.get('Image'))[any([n.get('Image')])],
|
||||||
v = self._get_url_artwork(v)
|
},
|
||||||
else:
|
'person': {'id': None, # not supported by tvdb
|
||||||
v = self._clean_data(v)
|
'name': n.get('Name', '').strip(),
|
||||||
cur_actor[k] = v
|
'url': None, # not supported by tvdb
|
||||||
cur_actors.append(cur_actor)
|
'image': None, # not supported by tvdb
|
||||||
|
'birthday': None, # not supported by tvdb
|
||||||
|
'deathday': None, # not supported by tvdb
|
||||||
|
'gender': None, # not supported by tvdb
|
||||||
|
'country': None, # not supported by tvdb
|
||||||
|
},
|
||||||
|
})
|
||||||
except (StandardError, Exception):
|
except (StandardError, Exception):
|
||||||
pass
|
pass
|
||||||
|
self._set_show_data(sid, 'actors', a)
|
||||||
self._set_show_data(sid, '_actors', cur_actors)
|
|
||||||
|
|
||||||
def _get_show_data(self, sid, language, get_ep_info=False):
|
def _get_show_data(self, sid, language, get_ep_info=False):
|
||||||
"""Takes a series ID, gets the epInfo URL and parses the TVDB
|
"""Takes a series ID, gets the epInfo URL and parses the TVDB
|
||||||
|
@ -822,14 +827,15 @@ class TvdbV1:
|
||||||
|
|
||||||
self._set_show_data(sid, k.lower(), v)
|
self._set_show_data(sid, k.lower(), v)
|
||||||
|
|
||||||
if get_ep_info:
|
# Parse actors
|
||||||
|
if self.config['actors_enabled']:
|
||||||
|
self._parse_actors(sid)
|
||||||
|
|
||||||
# Parse banners
|
# Parse banners
|
||||||
if self.config['banners_enabled']:
|
if self.config['banners_enabled']:
|
||||||
self._parse_banners(sid)
|
self._parse_banners(sid)
|
||||||
|
|
||||||
# Parse actors
|
if get_ep_info:
|
||||||
if self.config['actors_enabled']:
|
|
||||||
self._parse_actors(sid)
|
|
||||||
|
|
||||||
# Parse episode data
|
# Parse episode data
|
||||||
self.log('Getting all episodes of %s' % sid)
|
self.log('Getting all episodes of %s' % sid)
|
||||||
|
|
|
@ -61,7 +61,7 @@ CFG = None
|
||||||
CONFIG_FILE = None
|
CONFIG_FILE = None
|
||||||
|
|
||||||
# This is the version of the config we EXPECT to find
|
# This is the version of the config we EXPECT to find
|
||||||
CONFIG_VERSION = 16
|
CONFIG_VERSION = 17
|
||||||
|
|
||||||
# Default encryption version (0 for None)
|
# Default encryption version (0 for None)
|
||||||
ENCRYPTION_VERSION = 0
|
ENCRYPTION_VERSION = 0
|
||||||
|
|
|
@ -465,7 +465,8 @@ class ConfigMigrator:
|
||||||
13: 'Change default dereferrer url to blank',
|
13: 'Change default dereferrer url to blank',
|
||||||
14: 'Convert Trakt to multi-account',
|
14: 'Convert Trakt to multi-account',
|
||||||
15: 'Transmithe.net rebranded Nebulance',
|
15: 'Transmithe.net rebranded Nebulance',
|
||||||
16: 'Purge old cache image folders'}
|
16: 'Purge old cache image folders',
|
||||||
|
17: 'Add "vp9", "av1" to ignore words if not found'}
|
||||||
|
|
||||||
def migrate_config(self):
|
def migrate_config(self):
|
||||||
""" Calls each successive migration until the config is the same version as SG expects """
|
""" Calls each successive migration until the config is the same version as SG expects """
|
||||||
|
@ -844,3 +845,31 @@ class ConfigMigrator:
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
sickbeard.CACHE_DIR = cache_default
|
sickbeard.CACHE_DIR = cache_default
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def add_ignore_words(wordlist):
|
||||||
|
# add words to ignore list and insert spaces to improve the ui config readability
|
||||||
|
if not isinstance(wordlist, list):
|
||||||
|
wordlist = [wordlist]
|
||||||
|
config_words = sickbeard.IGNORE_WORDS.split(',')
|
||||||
|
new_list = []
|
||||||
|
using_regex = ''
|
||||||
|
for new_word in wordlist:
|
||||||
|
add_word = True
|
||||||
|
for ignore_word in config_words:
|
||||||
|
ignored = ignore_word.strip().lower()
|
||||||
|
if ignored.startswith('regex:'):
|
||||||
|
ignored = ignored.lstrip('regex:')
|
||||||
|
using_regex = 'regex:'
|
||||||
|
if ignored and ignored not in new_list:
|
||||||
|
new_list += [ignored]
|
||||||
|
if new_word in ignored:
|
||||||
|
add_word = False
|
||||||
|
if add_word:
|
||||||
|
new_list += [new_word]
|
||||||
|
|
||||||
|
sickbeard.IGNORE_WORDS = '%s%s' % (using_regex, ', '.join(new_list))
|
||||||
|
|
||||||
|
def _migrate_v17(self):
|
||||||
|
|
||||||
|
self.add_ignore_words(['vp9', 'av1'])
|
||||||
|
|
|
@ -20,9 +20,11 @@ from __future__ import print_function
|
||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
|
import codecs
|
||||||
import datetime
|
import datetime
|
||||||
import getpass
|
import getpass
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import io
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
|
@ -360,7 +362,7 @@ def moveAndSymlinkFile(srcFile, destFile):
|
||||||
copyFile(srcFile, destFile)
|
copyFile(srcFile, destFile)
|
||||||
|
|
||||||
|
|
||||||
def make_dirs(path):
|
def make_dirs(path, syno=True):
|
||||||
"""
|
"""
|
||||||
Creates any folders that are missing and assigns them the permissions of their
|
Creates any folders that are missing and assigns them the permissions of their
|
||||||
parents
|
parents
|
||||||
|
@ -394,6 +396,7 @@ def make_dirs(path):
|
||||||
ek.ek(os.mkdir, sofar)
|
ek.ek(os.mkdir, sofar)
|
||||||
# use normpath to remove end separator, otherwise checks permissions against itself
|
# use normpath to remove end separator, otherwise checks permissions against itself
|
||||||
chmodAsParent(ek.ek(os.path.normpath, sofar))
|
chmodAsParent(ek.ek(os.path.normpath, sofar))
|
||||||
|
if syno:
|
||||||
# do the library update for synoindex
|
# do the library update for synoindex
|
||||||
notifiers.NotifierFactory().get('SYNOINDEX').addFolder(sofar)
|
notifiers.NotifierFactory().get('SYNOINDEX').addFolder(sofar)
|
||||||
except (OSError, IOError) as e:
|
except (OSError, IOError) as e:
|
||||||
|
@ -1251,17 +1254,8 @@ def getURL(url, post_data=None, params=None, headers=None, timeout=30, session=N
|
||||||
|
|
||||||
if savename:
|
if savename:
|
||||||
try:
|
try:
|
||||||
with open(savename, 'wb') as fp:
|
write_file(savename, response, raw=True, raise_exceptions=raise_exceptions)
|
||||||
for chunk in response.iter_content(chunk_size=1024):
|
except (StandardError, Exception) as e:
|
||||||
if chunk:
|
|
||||||
fp.write(chunk)
|
|
||||||
fp.flush()
|
|
||||||
ek.ek(os.fsync, fp.fileno())
|
|
||||||
|
|
||||||
chmodAsParent(savename)
|
|
||||||
|
|
||||||
except EnvironmentError as e:
|
|
||||||
logger.log(u'Unable to save the file: ' + ex(e), logger.ERROR)
|
|
||||||
if raise_exceptions:
|
if raise_exceptions:
|
||||||
raise e
|
raise e
|
||||||
return
|
return
|
||||||
|
@ -1703,3 +1697,44 @@ def path_mapper(search, replace, subject):
|
||||||
result = os.path.normpath(re.sub(delim, '/', result))
|
result = os.path.normpath(re.sub(delim, '/', result))
|
||||||
|
|
||||||
return result, result != subject
|
return result, result != subject
|
||||||
|
|
||||||
|
|
||||||
|
def write_file(filepath, data, raw=False, xmltree=False, utf8=False, raise_exceptions=False):
|
||||||
|
|
||||||
|
result = False
|
||||||
|
|
||||||
|
if make_dirs(ek.ek(os.path.dirname, filepath), False):
|
||||||
|
try:
|
||||||
|
if raw:
|
||||||
|
with io.FileIO(filepath, 'wb') as fh:
|
||||||
|
for chunk in data.iter_content(chunk_size=1024):
|
||||||
|
if chunk:
|
||||||
|
fh.write(chunk)
|
||||||
|
fh.flush()
|
||||||
|
ek.ek(os.fsync, fh.fileno())
|
||||||
|
else:
|
||||||
|
w_mode = 'w'
|
||||||
|
if utf8:
|
||||||
|
w_mode = 'a'
|
||||||
|
with io.FileIO(filepath, 'wb') as fh:
|
||||||
|
fh.write(codecs.BOM_UTF8)
|
||||||
|
|
||||||
|
if xmltree:
|
||||||
|
with io.FileIO(filepath, w_mode) as fh:
|
||||||
|
if utf8:
|
||||||
|
data.write(fh, encoding='utf-8')
|
||||||
|
else:
|
||||||
|
data.write(fh)
|
||||||
|
else:
|
||||||
|
with io.FileIO(filepath, w_mode) as fh:
|
||||||
|
fh.write(data)
|
||||||
|
|
||||||
|
chmodAsParent(filepath)
|
||||||
|
|
||||||
|
result = True
|
||||||
|
except (EnvironmentError, IOError) as e:
|
||||||
|
logger.log('Unable to write file %s : %s' % (filepath, ex(e)), logger.ERROR)
|
||||||
|
if raise_exceptions:
|
||||||
|
raise e
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
|
@ -320,7 +320,6 @@ class GenericMetadata():
|
||||||
logger.DEBUG)
|
logger.DEBUG)
|
||||||
|
|
||||||
nfo_file_path = self.get_show_file_path(show_obj)
|
nfo_file_path = self.get_show_file_path(show_obj)
|
||||||
try:
|
|
||||||
with ek.ek(open, nfo_file_path, 'r') as xmlFileObj:
|
with ek.ek(open, nfo_file_path, 'r') as xmlFileObj:
|
||||||
show_xml = etree.ElementTree(file=xmlFileObj)
|
show_xml = etree.ElementTree(file=xmlFileObj)
|
||||||
|
|
||||||
|
@ -343,13 +342,9 @@ class GenericMetadata():
|
||||||
# Make it purdy
|
# Make it purdy
|
||||||
helpers.indentXML(root)
|
helpers.indentXML(root)
|
||||||
|
|
||||||
show_xml.write(nfo_file_path)
|
helpers.write_file(nfo_file_path, show_xml, xmltree=True, utf8=True)
|
||||||
helpers.chmodAsParent(nfo_file_path)
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
except IOError as e:
|
|
||||||
logger.log(u'Unable to write file %s - is the folder writable? %s' % (nfo_file_path, ex(e)),
|
|
||||||
logger.ERROR)
|
|
||||||
|
|
||||||
def create_fanart(self, show_obj):
|
def create_fanart(self, show_obj):
|
||||||
if self.fanart and show_obj and not self._has_fanart(show_obj):
|
if self.fanart and show_obj and not self._has_fanart(show_obj):
|
||||||
|
@ -476,27 +471,10 @@ class GenericMetadata():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
nfo_file_path = self.get_show_file_path(show_obj)
|
nfo_file_path = self.get_show_file_path(show_obj)
|
||||||
nfo_file_dir = ek.ek(os.path.dirname, nfo_file_path)
|
|
||||||
|
|
||||||
try:
|
logger.log(u'Writing show metadata file: %s' % nfo_file_path, logger.DEBUG)
|
||||||
if not ek.ek(os.path.isdir, nfo_file_dir):
|
|
||||||
logger.log(u"Metadata dir didn't exist, creating it at " + nfo_file_dir, logger.DEBUG)
|
|
||||||
ek.ek(os.makedirs, nfo_file_dir)
|
|
||||||
helpers.chmodAsParent(nfo_file_dir)
|
|
||||||
|
|
||||||
logger.log(u"Writing show nfo file to " + nfo_file_path, logger.DEBUG)
|
return helpers.write_file(nfo_file_path, data, xmltree=True, utf8=True)
|
||||||
|
|
||||||
nfo_file = ek.ek(open, nfo_file_path, 'w')
|
|
||||||
|
|
||||||
data.write(nfo_file, encoding="utf-8")
|
|
||||||
nfo_file.close()
|
|
||||||
helpers.chmodAsParent(nfo_file_path)
|
|
||||||
except IOError as e:
|
|
||||||
logger.log(u"Unable to write file to " + nfo_file_path + " - are you sure the folder is writable? " + ex(e),
|
|
||||||
logger.ERROR)
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def write_ep_file(self, ep_obj):
|
def write_ep_file(self, ep_obj):
|
||||||
"""
|
"""
|
||||||
|
@ -521,27 +499,10 @@ class GenericMetadata():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
nfo_file_path = self.get_episode_file_path(ep_obj)
|
nfo_file_path = self.get_episode_file_path(ep_obj)
|
||||||
nfo_file_dir = ek.ek(os.path.dirname, nfo_file_path)
|
|
||||||
|
|
||||||
try:
|
logger.log(u'Writing episode metadata file: %s' % nfo_file_path, logger.DEBUG)
|
||||||
if not ek.ek(os.path.isdir, nfo_file_dir):
|
|
||||||
logger.log(u"Metadata dir didn't exist, creating it at " + nfo_file_dir, logger.DEBUG)
|
|
||||||
ek.ek(os.makedirs, nfo_file_dir)
|
|
||||||
helpers.chmodAsParent(nfo_file_dir)
|
|
||||||
|
|
||||||
logger.log(u"Writing episode nfo file to " + nfo_file_path, logger.DEBUG)
|
return helpers.write_file(nfo_file_path, data, xmltree=True, utf8=True)
|
||||||
|
|
||||||
nfo_file = ek.ek(open, nfo_file_path, 'w')
|
|
||||||
|
|
||||||
data.write(nfo_file, encoding="utf-8")
|
|
||||||
nfo_file.close()
|
|
||||||
helpers.chmodAsParent(nfo_file_path)
|
|
||||||
except IOError as e:
|
|
||||||
logger.log(u"Unable to write file to " + nfo_file_path + " - are you sure the folder is writable? " + ex(e),
|
|
||||||
logger.ERROR)
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def save_thumbnail(self, ep_obj):
|
def save_thumbnail(self, ep_obj):
|
||||||
"""
|
"""
|
||||||
|
@ -911,12 +872,12 @@ class GenericMetadata():
|
||||||
if not self._valid_show(indexer_show_obj, show_obj):
|
if not self._valid_show(indexer_show_obj, show_obj):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
season_images = getattr(indexer_show_obj, '_banners', {}).get(
|
season_images = getattr(indexer_show_obj, 'banners', {}).get(
|
||||||
('season', 'seasonwide')['seasonwides' == image_type], {}).get(season, {})
|
('season', 'seasonwide')['seasonwides' == image_type], {}).get(season, {})
|
||||||
for image_id in season_images.keys():
|
for image_id in season_images.keys():
|
||||||
if season not in result:
|
if season not in result:
|
||||||
result[season] = {}
|
result[season] = {}
|
||||||
result[season][image_id] = season_images[image_id]['_bannerpath']
|
result[season][image_id] = season_images[image_id]['bannerpath']
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
|
@ -187,24 +187,7 @@ class KODIMetadata(generic.GenericMetadata):
|
||||||
if getattr(myShow, 'network', None) is not None:
|
if getattr(myShow, 'network', None) is not None:
|
||||||
studio.text = myShow['network']
|
studio.text = myShow['network']
|
||||||
|
|
||||||
if getattr(myShow, '_actors', None) is not None:
|
self.add_actor_element(myShow, etree, tv_node)
|
||||||
for actor in myShow['_actors']:
|
|
||||||
cur_actor = etree.SubElement(tv_node, 'actor')
|
|
||||||
|
|
||||||
cur_actor_name = etree.SubElement(cur_actor, 'name')
|
|
||||||
cur_actor_name_text = actor['name']
|
|
||||||
if isinstance(cur_actor_name_text, basestring):
|
|
||||||
cur_actor_name.text = cur_actor_name_text.strip()
|
|
||||||
|
|
||||||
cur_actor_role = etree.SubElement(cur_actor, 'role')
|
|
||||||
cur_actor_role_text = actor['role']
|
|
||||||
if cur_actor_role_text != None:
|
|
||||||
cur_actor_role.text = cur_actor_role_text
|
|
||||||
|
|
||||||
cur_actor_thumb = etree.SubElement(cur_actor, 'thumb')
|
|
||||||
cur_actor_thumb_text = actor['image']
|
|
||||||
if cur_actor_thumb_text != None:
|
|
||||||
cur_actor_thumb.text = cur_actor_thumb_text
|
|
||||||
|
|
||||||
# Make it purdy
|
# Make it purdy
|
||||||
helpers.indentXML(tv_node)
|
helpers.indentXML(tv_node)
|
||||||
|
@ -351,24 +334,7 @@ class KODIMetadata(generic.GenericMetadata):
|
||||||
cur_actor_name = etree.SubElement(cur_actor, 'name')
|
cur_actor_name = etree.SubElement(cur_actor, 'name')
|
||||||
cur_actor_name.text = actor
|
cur_actor_name.text = actor
|
||||||
|
|
||||||
if getattr(myEp, '_actors', None) is not None:
|
self.add_actor_element(myShow, etree, episode)
|
||||||
for actor in myShow['_actors']:
|
|
||||||
cur_actor = etree.SubElement(episode, 'actor')
|
|
||||||
|
|
||||||
cur_actor_name = etree.SubElement(cur_actor, 'name')
|
|
||||||
cur_actor_name_text = actor['name']
|
|
||||||
if isinstance(cur_actor_name_text, basestring):
|
|
||||||
cur_actor_name.text = cur_actor_name_text.strip()
|
|
||||||
|
|
||||||
cur_actor_role = etree.SubElement(cur_actor, 'role')
|
|
||||||
cur_actor_role_text = actor['role']
|
|
||||||
if cur_actor_role_text != None:
|
|
||||||
cur_actor_role.text = cur_actor_role_text
|
|
||||||
|
|
||||||
cur_actor_thumb = etree.SubElement(cur_actor, 'thumb')
|
|
||||||
cur_actor_thumb_text = actor['image']
|
|
||||||
if cur_actor_thumb_text != None:
|
|
||||||
cur_actor_thumb.text = cur_actor_thumb_text
|
|
||||||
|
|
||||||
# Make it purdy
|
# Make it purdy
|
||||||
helpers.indentXML(rootNode)
|
helpers.indentXML(rootNode)
|
||||||
|
@ -377,6 +343,26 @@ class KODIMetadata(generic.GenericMetadata):
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def add_actor_element(my_show, et, node):
|
||||||
|
for actor in getattr(my_show, 'actors', []):
|
||||||
|
cur_actor = et.SubElement(node, 'actor')
|
||||||
|
|
||||||
|
cur_actor_name = et.SubElement(cur_actor, 'name')
|
||||||
|
cur_actor_name_text = actor['person']['name']
|
||||||
|
if cur_actor_name_text:
|
||||||
|
cur_actor_name.text = cur_actor_name_text
|
||||||
|
|
||||||
|
cur_actor_role = et.SubElement(cur_actor, 'role')
|
||||||
|
cur_actor_role_text = actor['character']['name']
|
||||||
|
if cur_actor_role_text:
|
||||||
|
cur_actor_role.text = cur_actor_role_text
|
||||||
|
|
||||||
|
cur_actor_thumb = et.SubElement(cur_actor, 'thumb')
|
||||||
|
cur_actor_thumb_text = actor['character']['image']
|
||||||
|
if None is not cur_actor_thumb_text:
|
||||||
|
cur_actor_thumb.text = cur_actor_thumb_text
|
||||||
|
|
||||||
|
|
||||||
# present a standard "interface" from the module
|
# present a standard "interface" from the module
|
||||||
metadata_class = KODIMetadata
|
metadata_class = KODIMetadata
|
||||||
|
|
|
@ -199,14 +199,7 @@ class Mede8erMetadata(mediabrowser.MediaBrowserMetadata):
|
||||||
Runtime.text = myShow['runtime']
|
Runtime.text = myShow['runtime']
|
||||||
|
|
||||||
cast = etree.SubElement(tv_node, "cast")
|
cast = etree.SubElement(tv_node, "cast")
|
||||||
|
self.add_actor_element(myShow, etree, cast)
|
||||||
if getattr(myShow, '_actors', None) is not None:
|
|
||||||
for actor in myShow['_actors']:
|
|
||||||
cur_actor_name_text = actor['name']
|
|
||||||
|
|
||||||
if cur_actor_name_text != None and cur_actor_name_text.strip():
|
|
||||||
cur_actor = etree.SubElement(cast, "actor")
|
|
||||||
cur_actor.text = cur_actor_name_text.strip()
|
|
||||||
|
|
||||||
helpers.indentXML(rootNode)
|
helpers.indentXML(rootNode)
|
||||||
|
|
||||||
|
@ -333,14 +326,7 @@ class Mede8erMetadata(mediabrowser.MediaBrowserMetadata):
|
||||||
credits.text = credits_text
|
credits.text = credits_text
|
||||||
|
|
||||||
cast = etree.SubElement(episode, "cast")
|
cast = etree.SubElement(episode, "cast")
|
||||||
|
self.add_actor_element(myShow, etree, cast)
|
||||||
if getattr(myShow, '_actors', None) is not None:
|
|
||||||
for actor in myShow['_actors']:
|
|
||||||
cur_actor_name_text = actor['name']
|
|
||||||
|
|
||||||
if cur_actor_name_text != None and cur_actor_name_text.strip():
|
|
||||||
cur_actor = etree.SubElement(cast, "actor")
|
|
||||||
cur_actor.text = cur_actor_name_text.strip()
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# append data from (if any) related episodes
|
# append data from (if any) related episodes
|
||||||
|
@ -362,6 +348,17 @@ class Mede8erMetadata(mediabrowser.MediaBrowserMetadata):
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def add_actor_element(my_show, et, node):
|
||||||
|
for actor in getattr(my_show, 'actors', []):
|
||||||
|
cur_actor_name_text = actor['character']['name'] and actor['person']['name'] \
|
||||||
|
and actor['character']['name'] != actor['person']['name'] \
|
||||||
|
and '%s (%s)' % (actor['character']['name'], actor['person']['name']) \
|
||||||
|
or actor['person']['name'] or actor['character']['name']
|
||||||
|
if cur_actor_name_text:
|
||||||
|
cur_actor = et.SubElement(node, 'actor')
|
||||||
|
cur_actor.text = cur_actor_name_text
|
||||||
|
|
||||||
|
|
||||||
# present a standard "interface" from the module
|
# present a standard "interface" from the module
|
||||||
metadata_class = Mede8erMetadata
|
metadata_class = Mede8erMetadata
|
||||||
|
|
|
@ -362,17 +362,19 @@ class MediaBrowserMetadata(generic.GenericMetadata):
|
||||||
if getattr(myShow, 'network', None) is not None:
|
if getattr(myShow, 'network', None) is not None:
|
||||||
Studio.text = myShow['network']
|
Studio.text = myShow['network']
|
||||||
|
|
||||||
Persons = etree.SubElement(tv_node, "Persons")
|
Persons = etree.SubElement(tv_node, 'Persons')
|
||||||
if getattr(myShow, 'actors', None) is not None:
|
for actor in getattr(myShow, 'actors', []):
|
||||||
for actor in myShow['_actors']:
|
cur_actor = etree.SubElement(Persons, 'Person')
|
||||||
cur_actor = etree.SubElement(Persons, "Person")
|
|
||||||
cur_actor_name = etree.SubElement(cur_actor, "Name")
|
cur_actor_name = etree.SubElement(cur_actor, 'Name')
|
||||||
cur_actor_name.text = actor['name'].strip()
|
cur_actor_name.text = actor['person']['name']
|
||||||
cur_actor_type = etree.SubElement(cur_actor, "Type")
|
|
||||||
cur_actor_type.text = "Actor"
|
cur_actor_type = etree.SubElement(cur_actor, 'Type')
|
||||||
cur_actor_role = etree.SubElement(cur_actor, "Role")
|
cur_actor_type.text = 'Actor'
|
||||||
cur_actor_role_text = actor['role']
|
|
||||||
if cur_actor_role_text != None:
|
cur_actor_role = etree.SubElement(cur_actor, 'Role')
|
||||||
|
cur_actor_role_text = actor['character']['name']
|
||||||
|
if cur_actor_role_text:
|
||||||
cur_actor_role.text = cur_actor_role_text
|
cur_actor_role.text = cur_actor_role_text
|
||||||
|
|
||||||
helpers.indentXML(tv_node)
|
helpers.indentXML(tv_node)
|
||||||
|
|
|
@ -252,15 +252,16 @@ class TIVOMetadata(generic.GenericMetadata):
|
||||||
|
|
||||||
# This must be entered as yyyy-mm-ddThh:mm:ssZ (the t is capitalized and never changes, the Z is also
|
# This must be entered as yyyy-mm-ddThh:mm:ssZ (the t is capitalized and never changes, the Z is also
|
||||||
# capitalized and never changes). This is the original air date of the episode.
|
# capitalized and never changes). This is the original air date of the episode.
|
||||||
# NOTE: Hard coded the time to T00:00:00Z as we really don't know when during the day the first run happened.
|
# NOTE: Hard coded the time to T00:00:00Z as we really don't know when during the day the first run happened
|
||||||
if curEpToWrite.airdate != datetime.date.fromordinal(1):
|
if curEpToWrite.airdate != datetime.date.fromordinal(1):
|
||||||
data += ("originalAirDate : " + str(curEpToWrite.airdate) + "T00:00:00Z\n")
|
data += ("originalAirDate : " + str(curEpToWrite.airdate) + "T00:00:00Z\n")
|
||||||
|
|
||||||
# This shows up at the beginning of the description on the Program screen and on the Details screen.
|
# This shows up at the beginning of the description on the Program screen and on the Details screen.
|
||||||
if getattr(myShow, 'actors', None) is not None:
|
for actor in getattr(myShow, 'actors', []):
|
||||||
for actor in myShow["actors"].split('|'):
|
data += ('vActor : %s\n' % actor['character']['name'] and actor['person']['name']
|
||||||
if actor:
|
and actor['character']['name'] != actor['person']['name']
|
||||||
data += ("vActor : " + actor + "\n")
|
and '%s (%s)' % (actor['character']['name'], actor['person']['name'])
|
||||||
|
or actor['person']['name'] or actor['character']['name'])
|
||||||
|
|
||||||
# This is shown on both the Program screen and the Details screen.
|
# This is shown on both the Program screen and the Details screen.
|
||||||
if getattr(myEp, 'rating', None) is not None:
|
if getattr(myEp, 'rating', None) is not None:
|
||||||
|
|
|
@ -275,14 +275,15 @@ class WDTVMetadata(generic.GenericMetadata):
|
||||||
if director_text is not None:
|
if director_text is not None:
|
||||||
director.text = director_text
|
director.text = director_text
|
||||||
|
|
||||||
if getattr(myShow, '_actors', None) is not None:
|
for actor in getattr(myShow, 'actors', []):
|
||||||
for actor in myShow['_actors']:
|
cur_actor = etree.SubElement(episode, 'actor')
|
||||||
cur_actor = etree.SubElement(episode, "actor")
|
|
||||||
cur_actor_name = etree.SubElement(cur_actor, "name")
|
cur_actor_name = etree.SubElement(cur_actor, 'name')
|
||||||
cur_actor_name.text = actor['name']
|
cur_actor_name.text = actor['person']['name']
|
||||||
cur_actor_role = etree.SubElement(cur_actor, "role")
|
|
||||||
cur_actor_role_text = actor['role']
|
cur_actor_role = etree.SubElement(cur_actor, 'role')
|
||||||
if cur_actor_role_text != None:
|
cur_actor_role_text = actor['character']['name']
|
||||||
|
if cur_actor_role_text:
|
||||||
cur_actor_role.text = cur_actor_role_text
|
cur_actor_role.text = cur_actor_role_text
|
||||||
|
|
||||||
overview = etree.SubElement(episode, "overview")
|
overview = etree.SubElement(episode, "overview")
|
||||||
|
|
|
@ -187,24 +187,7 @@ class XBMC_12PlusMetadata(generic.GenericMetadata):
|
||||||
if getattr(myShow, 'network', None) is not None:
|
if getattr(myShow, 'network', None) is not None:
|
||||||
studio.text = myShow["network"]
|
studio.text = myShow["network"]
|
||||||
|
|
||||||
if getattr(myShow, '_actors', None) is not None:
|
self.add_actor_element(myShow, etree, tv_node)
|
||||||
for actor in myShow['_actors']:
|
|
||||||
cur_actor = etree.SubElement(tv_node, "actor")
|
|
||||||
|
|
||||||
cur_actor_name = etree.SubElement(cur_actor, "name")
|
|
||||||
cur_actor_name_text = actor['name']
|
|
||||||
if isinstance(cur_actor_name_text, basestring):
|
|
||||||
cur_actor_name.text = cur_actor_name_text.strip()
|
|
||||||
|
|
||||||
cur_actor_role = etree.SubElement(cur_actor, "role")
|
|
||||||
cur_actor_role_text = actor['role']
|
|
||||||
if cur_actor_role_text != None:
|
|
||||||
cur_actor_role.text = cur_actor_role_text
|
|
||||||
|
|
||||||
cur_actor_thumb = etree.SubElement(cur_actor, "thumb")
|
|
||||||
cur_actor_thumb_text = actor['image']
|
|
||||||
if cur_actor_thumb_text != None:
|
|
||||||
cur_actor_thumb.text = cur_actor_thumb_text
|
|
||||||
|
|
||||||
# Make it purdy
|
# Make it purdy
|
||||||
helpers.indentXML(tv_node)
|
helpers.indentXML(tv_node)
|
||||||
|
@ -354,24 +337,7 @@ class XBMC_12PlusMetadata(generic.GenericMetadata):
|
||||||
cur_actor_name = etree.SubElement(cur_actor, "name")
|
cur_actor_name = etree.SubElement(cur_actor, "name")
|
||||||
cur_actor_name.text = actor
|
cur_actor_name.text = actor
|
||||||
|
|
||||||
if getattr(myEp, '_actors', None) is not None:
|
self.add_actor_element(myShow, etree, episode)
|
||||||
for actor in myShow['_actors']:
|
|
||||||
cur_actor = etree.SubElement(episode, "actor")
|
|
||||||
|
|
||||||
cur_actor_name = etree.SubElement(cur_actor, "name")
|
|
||||||
cur_actor_name_text = actor['name']
|
|
||||||
if isinstance(cur_actor_name_text, basestring):
|
|
||||||
cur_actor_name.text = cur_actor_name_text.strip()
|
|
||||||
|
|
||||||
cur_actor_role = etree.SubElement(cur_actor, "role")
|
|
||||||
cur_actor_role_text = actor['role']
|
|
||||||
if cur_actor_role_text != None:
|
|
||||||
cur_actor_role.text = cur_actor_role_text
|
|
||||||
|
|
||||||
cur_actor_thumb = etree.SubElement(cur_actor, "thumb")
|
|
||||||
cur_actor_thumb_text = actor['image']
|
|
||||||
if cur_actor_thumb_text != None:
|
|
||||||
cur_actor_thumb.text = cur_actor_thumb_text
|
|
||||||
|
|
||||||
# Make it purdy
|
# Make it purdy
|
||||||
helpers.indentXML(rootNode)
|
helpers.indentXML(rootNode)
|
||||||
|
@ -380,6 +346,26 @@ class XBMC_12PlusMetadata(generic.GenericMetadata):
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def add_actor_element(my_show, et, node):
|
||||||
|
for actor in getattr(my_show, 'actors', []):
|
||||||
|
cur_actor = et.SubElement(node, 'actor')
|
||||||
|
|
||||||
|
cur_actor_name = et.SubElement(cur_actor, 'name')
|
||||||
|
cur_actor_name_text = actor['person']['name']
|
||||||
|
if cur_actor_name_text:
|
||||||
|
cur_actor_name.text = cur_actor_name_text
|
||||||
|
|
||||||
|
cur_actor_role = et.SubElement(cur_actor, 'role')
|
||||||
|
cur_actor_role_text = actor['character']['name']
|
||||||
|
if cur_actor_role_text:
|
||||||
|
cur_actor_role.text = cur_actor_role_text
|
||||||
|
|
||||||
|
cur_actor_thumb = et.SubElement(cur_actor, 'thumb')
|
||||||
|
cur_actor_thumb_text = actor['character']['image']
|
||||||
|
if None is not cur_actor_thumb_text:
|
||||||
|
cur_actor_thumb.text = cur_actor_thumb_text
|
||||||
|
|
||||||
|
|
||||||
# present a standard "interface" from the module
|
# present a standard "interface" from the module
|
||||||
metadata_class = XBMC_12PlusMetadata
|
metadata_class = XBMC_12PlusMetadata
|
||||||
|
|
Loading…
Reference in a new issue