Merge remote-tracking branch 'remotes/origin/develop' into tv
This commit is contained in:
@@ -1,15 +1,25 @@
|
||||
#So you feel like posting a bug, sending me a pull request or just telling me how awesome I am. No problem!
|
||||
## Got a issue/feature request or submitting a pull request?
|
||||
|
||||
##Just make sure you think of the following things:
|
||||
Make sure you think of the following things:
|
||||
|
||||
* Search through the existing (and closed) issues first. See if you can get your answer there.
|
||||
## Issue
|
||||
* Search through the existing (and closed) issues first, see if you can get your answer there.
|
||||
* Double check the result manually, because it could be an external issue.
|
||||
* Post logs! Without seeing what is going on, I can't reproduce the error.
|
||||
* What is the movie + quality you are searching for.
|
||||
* What are you settings for the specific problem.
|
||||
* What providers are you using. (While your logs include these, scanning through hundred of lines of log isn't my hobby).
|
||||
* Give me a short step by step of how to reproduce.
|
||||
* Also check the logs before submitting, obvious errors like permission or http errors are often not related to CP.
|
||||
* What is the movie + quality you are searching for?
|
||||
* What are you're settings for the specific problem?
|
||||
* What providers are you using? (While you're logs include these, scanning through hundred of lines of log isn't our hobby)
|
||||
* Post the logs from config directory, please do not copy paste the UI. Use pastebin to store these logs!
|
||||
* Give a short step by step of how to reproduce the error.
|
||||
* What hardware / OS are you using and what are the limits? NAS can be slow and maybe have a different python installed then when you use CP on OSX or Windows for example.
|
||||
* I will mark issues with the "can't reproduce" tag. Don't go asking me "why closed" if it clearly says the issue in the tag ;)
|
||||
* I will mark issues with the "can't reproduce" tag. Don't go asking "why closed" if it clearly says the issue in the tag ;)
|
||||
* If you're running on a NAS (QNAP, Austor etc..) with pre-made packages, make sure these are setup to use our source repo (RuudBurger/CouchPotatoServer) and nothing else!!
|
||||
|
||||
**If I don't get enough info, the chance of the issue getting closed is a lot bigger ;)**
|
||||
## Pull Request
|
||||
* Make sure you're pull request is made for develop branch (or relevant feature branch)
|
||||
* Have you tested your PR? If not, why?
|
||||
* Are there any limitations of your PR we should know of?
|
||||
* Make sure to keep you're PR up-to-date with the branch you're trying to push into.
|
||||
|
||||
**If we don't get enough info, the chance of the issue getting closed is a lot bigger ;)**
|
||||
|
||||
@@ -11,6 +11,9 @@ import sys
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
def fnEscape(pattern):
|
||||
return pattern.replace('[','[[').replace(']','[]]').replace('[[','[[]')
|
||||
|
||||
def link(src, dst):
|
||||
if os.name == 'nt':
|
||||
import ctypes
|
||||
|
||||
@@ -46,6 +46,14 @@ config = [{
|
||||
'advanced': True,
|
||||
'description': 'Only scan new movie folder at remote XBMC servers. Works if movie location is the same.',
|
||||
},
|
||||
{
|
||||
'name': 'force_full_scan',
|
||||
'label': 'Always do a full scan',
|
||||
'default': 0,
|
||||
'type': 'bool',
|
||||
'advanced': True,
|
||||
'description': 'Do a full scan instead of only the new movie. Useful if the XBMC path is different from the path CPS uses.',
|
||||
},
|
||||
{
|
||||
'name': 'on_snatch',
|
||||
'default': 0,
|
||||
|
||||
@@ -36,7 +36,7 @@ class XBMC(Notification):
|
||||
|
||||
if data and data.get('destination_dir') and (not self.conf('only_first') or hosts.index(host) == 0):
|
||||
param = {}
|
||||
if self.conf('remote_dir_scan') or socket.getfqdn('localhost') == socket.getfqdn(host.split(':')[0]):
|
||||
if not self.conf('force_full_scan') and (self.conf('remote_dir_scan') or socket.getfqdn('localhost') == socket.getfqdn(host.split(':')[0])):
|
||||
param = {'directory': data['destination_dir']}
|
||||
|
||||
calls.append(('VideoLibrary.Scan', param))
|
||||
|
||||
@@ -3,7 +3,7 @@ from couchpotato.api import addApiView
|
||||
from couchpotato.core.event import addEvent, fireEvent, fireEventAsync
|
||||
from couchpotato.core.helpers.encoding import toUnicode, ss, sp
|
||||
from couchpotato.core.helpers.variable import getExt, mergeDicts, getTitle, \
|
||||
getImdb, link, symlink, tryInt, splitString
|
||||
getImdb, link, symlink, tryInt, splitString, fnEscape
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.plugins.base import Plugin
|
||||
from couchpotato.core.settings.model import Library, File, Profile, Release, \
|
||||
@@ -644,7 +644,7 @@ Remove it if you want it to be renamed (again, or at least let it try again)
|
||||
|
||||
# Match all found ignore files with the tag_files and delete if found
|
||||
for tag_file in tag_files:
|
||||
ignore_file = fnmatch.filter(ignore_files, '%s.%s.ignore' % (re.escape(os.path.splitext(tag_file)[0]), tag if tag else '*'))
|
||||
ignore_file = fnmatch.filter(ignore_files, fnEscape('%s.%s.ignore' % (os.path.splitext(tag_file)[0], tag if tag else '*')))
|
||||
for filename in ignore_file:
|
||||
try:
|
||||
os.remove(filename)
|
||||
@@ -677,7 +677,7 @@ Remove it if you want it to be renamed (again, or at least let it try again)
|
||||
|
||||
# Match all found ignore files with the tag_files and return True found
|
||||
for tag_file in tag_files:
|
||||
ignore_file = fnmatch.filter(ignore_files, '%s.%s.ignore' % (os.path.splitext(tag_file)[0], tag if tag else '*'))
|
||||
ignore_file = fnmatch.filter(ignore_files, fnEscape('%s.%s.ignore' % (os.path.splitext(tag_file)[0], tag if tag else '*')))
|
||||
if ignore_file:
|
||||
return True
|
||||
|
||||
|
||||
@@ -454,7 +454,7 @@ class Scanner(Plugin):
|
||||
data['resolution_width'] = meta.get('resolution_width', 720)
|
||||
data['resolution_height'] = meta.get('resolution_height', 480)
|
||||
data['audio_channels'] = meta.get('audio_channels', 2.0)
|
||||
data['aspect'] = meta.get('resolution_width', 720) / meta.get('resolution_height', 480)
|
||||
data['aspect'] = round(float(meta.get('resolution_width', 720)) / meta.get('resolution_height', 480), 2)
|
||||
except:
|
||||
log.debug('Error parsing metadata: %s %s', (cur_file, traceback.format_exc()))
|
||||
pass
|
||||
|
||||
@@ -84,6 +84,10 @@ class OMDBAPI(MovieProvider):
|
||||
|
||||
year = tryInt(movie.get('Year', ''))
|
||||
|
||||
actors = {}
|
||||
for actor in splitString(movie.get('Actors', '')):
|
||||
actors[actor] = '' #omdb does not return actor roles
|
||||
|
||||
movie_data = {
|
||||
'type': 'movie',
|
||||
'via_imdb': True,
|
||||
@@ -105,7 +109,7 @@ class OMDBAPI(MovieProvider):
|
||||
'genres': splitString(movie.get('Genre', '')),
|
||||
'directors': splitString(movie.get('Director', '')),
|
||||
'writers': splitString(movie.get('Writer', '')),
|
||||
'actors': splitString(movie.get('Actors', '')),
|
||||
'actor_roles': actors,
|
||||
}
|
||||
movie_data = dict((k, v) for k, v in movie_data.iteritems() if v)
|
||||
except:
|
||||
|
||||
@@ -92,6 +92,13 @@ class TheMovieDb(MovieProvider):
|
||||
poster_original = self.getImage(movie, type = 'poster', size = 'original')
|
||||
backdrop_original = self.getImage(movie, type = 'backdrop', size = 'original')
|
||||
|
||||
images = {
|
||||
'poster': [poster] if poster else [],
|
||||
#'backdrop': [backdrop] if backdrop else [],
|
||||
'poster_original': [poster_original] if poster_original else [],
|
||||
'backdrop_original': [backdrop_original] if backdrop_original else [],
|
||||
}
|
||||
|
||||
# Genres
|
||||
try:
|
||||
genres = [genre.name for genre in movie.genres]
|
||||
@@ -103,18 +110,22 @@ class TheMovieDb(MovieProvider):
|
||||
if not movie.releasedate or year == '1900' or year.lower() == 'none':
|
||||
year = None
|
||||
|
||||
# Gather actors data
|
||||
actors = {}
|
||||
for cast_item in movie.cast:
|
||||
try:
|
||||
actors[toUnicode(cast_item.name)] = toUnicode(cast_item.character)
|
||||
images['actor %s' % toUnicode(cast_item.name)] = self.getImage(cast_item, type = 'profile', size = 'original')
|
||||
except:
|
||||
log.debug('Error getting cast info for %s: %s', (cast_item, traceback.format_exc()))
|
||||
|
||||
movie_data = {
|
||||
'type': 'movie',
|
||||
'via_tmdb': True,
|
||||
'tmdb_id': movie.id,
|
||||
'titles': [toUnicode(movie.title)],
|
||||
'original_title': movie.originaltitle,
|
||||
'images': {
|
||||
'poster': [poster] if poster else [],
|
||||
#'backdrop': [backdrop] if backdrop else [],
|
||||
'poster_original': [poster_original] if poster_original else [],
|
||||
'backdrop_original': [backdrop_original] if backdrop_original else [],
|
||||
},
|
||||
'images': images,
|
||||
'imdb': movie.imdb,
|
||||
'runtime': movie.runtime,
|
||||
'released': str(movie.releasedate),
|
||||
@@ -122,6 +133,7 @@ class TheMovieDb(MovieProvider):
|
||||
'plot': movie.overview,
|
||||
'genres': genres,
|
||||
'collection': getattr(movie.collection, 'name', None),
|
||||
'actor_roles': actors
|
||||
}
|
||||
|
||||
movie_data = dict((k, v) for k, v in movie_data.iteritems() if v)
|
||||
@@ -145,7 +157,7 @@ class TheMovieDb(MovieProvider):
|
||||
try:
|
||||
image_url = getattr(movie, type).geturl(size = 'original')
|
||||
except:
|
||||
log.debug('Failed getting %s.%s for "%s"', (type, size, movie.title))
|
||||
log.debug('Failed getting %s.%s for "%s"', (type, size, movie))
|
||||
|
||||
return image_url
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ class XBMC(MetaDataBase):
|
||||
name = type
|
||||
|
||||
try:
|
||||
if data['library'].get(type):
|
||||
if movie_info.get(type):
|
||||
el = SubElement(nfoxml, name)
|
||||
el.text = toUnicode(movie_info.get(type, ''))
|
||||
except:
|
||||
@@ -89,10 +89,18 @@ class XBMC(MetaDataBase):
|
||||
genres.text = toUnicode(genre)
|
||||
|
||||
# Actors
|
||||
for actor in movie_info.get('actors', []):
|
||||
actors = SubElement(nfoxml, 'actor')
|
||||
name = SubElement(actors, 'name')
|
||||
name.text = toUnicode(actor)
|
||||
for actor_name in movie_info.get('actor_roles', {}):
|
||||
role_name = movie_info['actor_roles'][actor_name]
|
||||
|
||||
actor = SubElement(nfoxml, 'actor')
|
||||
name = SubElement(actor, 'name')
|
||||
name.text = toUnicode(actor_name)
|
||||
if role_name:
|
||||
role = SubElement(actor, 'role')
|
||||
role.text = toUnicode(role_name)
|
||||
if movie_info['images'].get('actor %s' % actor_name, ''):
|
||||
thumb = SubElement(actor, 'thumb')
|
||||
thumb.text = toUnicode(movie_info['images'].get('actor %s' % actor_name))
|
||||
|
||||
# Directors
|
||||
for director_name in movie_info.get('directors', []):
|
||||
@@ -112,6 +120,51 @@ class XBMC(MetaDataBase):
|
||||
sorttitle = SubElement(nfoxml, 'sorttitle')
|
||||
sorttitle.text = '%s %s' % (toUnicode(collection_name), movie_info.get('year'))
|
||||
|
||||
# Images
|
||||
for image_url in movie_info['images']['poster_original']:
|
||||
image = SubElement(nfoxml, 'thumb')
|
||||
image.text = toUnicode(image_url)
|
||||
fanart = SubElement(nfoxml, 'fanart')
|
||||
for image_url in movie_info['images']['backdrop_original']:
|
||||
image = SubElement(fanart, 'thumb')
|
||||
image.text = toUnicode(image_url)
|
||||
|
||||
# Add trailer if found
|
||||
trailer_found = False
|
||||
if data.get('renamed_files'):
|
||||
for filename in data.get('renamed_files'):
|
||||
if 'trailer' in filename:
|
||||
trailer = SubElement(nfoxml, 'trailer')
|
||||
trailer.text = toUnicode(filename)
|
||||
trailer_found = True
|
||||
if not trailer_found and data['files'].get('trailer'):
|
||||
trailer = SubElement(nfoxml, 'trailer')
|
||||
trailer.text = toUnicode(data['files']['trailer'][0])
|
||||
|
||||
# Add file metadata
|
||||
fileinfo = SubElement(nfoxml, 'fileinfo')
|
||||
streamdetails = SubElement(fileinfo, 'streamdetails')
|
||||
|
||||
# Video data
|
||||
if data['meta_data'].get('video'):
|
||||
video = SubElement(streamdetails, 'video')
|
||||
codec = SubElement(video, 'codec')
|
||||
codec.text = toUnicode(data['meta_data']['video'])
|
||||
aspect = SubElement(video, 'aspect')
|
||||
aspect.text = str(data['meta_data']['aspect'])
|
||||
width = SubElement(video, 'width')
|
||||
width.text = str(data['meta_data']['resolution_width'])
|
||||
height = SubElement(video, 'height')
|
||||
height.text = str(data['meta_data']['resolution_height'])
|
||||
|
||||
# Audio data
|
||||
if data['meta_data'].get('audio'):
|
||||
audio = SubElement(streamdetails, 'audio')
|
||||
codec = SubElement(audio, 'codec')
|
||||
codec.text = toUnicode(data['meta_data'].get('audio'))
|
||||
channels = SubElement(audio, 'channels')
|
||||
channels.text = toUnicode(data['meta_data'].get('audio_channels'))
|
||||
|
||||
# Clean up the xml and return it
|
||||
nfoxml = xml.dom.minidom.parseString(tostring(nfoxml))
|
||||
xml_string = nfoxml.toprettyxml(indent = ' ')
|
||||
|
||||
@@ -12,6 +12,7 @@ from urllib2 import HTTPError
|
||||
from urlparse import urlparse
|
||||
import time
|
||||
import traceback
|
||||
import urllib2
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
@@ -161,7 +162,15 @@ class Base(NZBProvider, RSS):
|
||||
return 'try_next'
|
||||
|
||||
try:
|
||||
data = self.urlopen(url, show_error = False)
|
||||
# Get final redirected url
|
||||
log.debug('Checking %s for redirects.', url)
|
||||
req = urllib2.Request(url)
|
||||
res = urllib2.urlopen(req)
|
||||
finalurl = res.geturl()
|
||||
if finalurl != url:
|
||||
log.debug('Redirect url used: %s', finalurl)
|
||||
|
||||
data = self.urlopen(finalurl, show_error = False)
|
||||
self.limits_reached[host] = False
|
||||
return data
|
||||
except HTTPError, e:
|
||||
@@ -217,4 +226,4 @@ class Episode(EpisodeProvider, Base):
|
||||
'apikey': api_key,
|
||||
'extended': 1
|
||||
})
|
||||
return query
|
||||
return query
|
||||
|
||||
Reference in New Issue
Block a user