From a466cbcf16e19687a970f52d38ad28b7bc3b6e83 Mon Sep 17 00:00:00 2001 From: mano3m Date: Tue, 19 Nov 2013 16:13:22 +0100 Subject: [PATCH 01/10] [Metadata][XBMC] Fix nfo data Fixes #1412 and @Lennong MPAA section --- couchpotato/core/providers/metadata/xbmc/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/couchpotato/core/providers/metadata/xbmc/main.py b/couchpotato/core/providers/metadata/xbmc/main.py index 7073363d..56032796 100644 --- a/couchpotato/core/providers/metadata/xbmc/main.py +++ b/couchpotato/core/providers/metadata/xbmc/main.py @@ -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: From 2c1c57333c4b3e5af12cc3ecabfc092590d3406e Mon Sep 17 00:00:00 2001 From: mano3m Date: Tue, 19 Nov 2013 16:30:56 +0100 Subject: [PATCH 02/10] [Metadata][XBMC] Add trailer to nfo --- couchpotato/core/providers/metadata/xbmc/main.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/couchpotato/core/providers/metadata/xbmc/main.py b/couchpotato/core/providers/metadata/xbmc/main.py index 56032796..e287cbd8 100644 --- a/couchpotato/core/providers/metadata/xbmc/main.py +++ b/couchpotato/core/providers/metadata/xbmc/main.py @@ -112,6 +112,18 @@ class XBMC(MetaDataBase): sorttitle = SubElement(nfoxml, 'sorttitle') sorttitle.text = '%s %s' % (toUnicode(collection_name), movie_info.get('year')) + # 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]) + # Clean up the xml and return it nfoxml = xml.dom.minidom.parseString(tostring(nfoxml)) xml_string = nfoxml.toprettyxml(indent = ' ') From bd1bb1ee9172d91666cc91fdd783c7c6ec4dd872 Mon Sep 17 00:00:00 2001 From: mano3m Date: Tue, 19 Nov 2013 18:30:09 +0100 Subject: [PATCH 03/10] [Metadata][XBMC] Add images to nfo --- couchpotato/core/providers/metadata/xbmc/main.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/couchpotato/core/providers/metadata/xbmc/main.py b/couchpotato/core/providers/metadata/xbmc/main.py index e287cbd8..09e523aa 100644 --- a/couchpotato/core/providers/metadata/xbmc/main.py +++ b/couchpotato/core/providers/metadata/xbmc/main.py @@ -112,6 +112,15 @@ 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'): From e4993eac24d7c6d376ef9183fa84096217e0f447 Mon Sep 17 00:00:00 2001 From: mano3m Date: Wed, 20 Nov 2013 00:32:26 +0100 Subject: [PATCH 04/10] [Metadata][XBMC] Add actors to CPS info and nfo --- .../core/providers/info/omdbapi/main.py | 2 +- .../core/providers/info/themoviedb/main.py | 21 +++++++++++++------ .../core/providers/metadata/xbmc/main.py | 14 +++++++++---- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/couchpotato/core/providers/info/omdbapi/main.py b/couchpotato/core/providers/info/omdbapi/main.py index 47374f47..c5db5eab 100755 --- a/couchpotato/core/providers/info/omdbapi/main.py +++ b/couchpotato/core/providers/info/omdbapi/main.py @@ -105,7 +105,7 @@ class OMDBAPI(MovieProvider): 'genres': splitString(movie.get('Genre', '')), 'directors': splitString(movie.get('Director', '')), 'writers': splitString(movie.get('Writer', '')), - 'actors': splitString(movie.get('Actors', '')), + 'actors': [{actor: ''} for actor in splitString(movie.get('Actors', ''))], } movie_data = dict((k, v) for k, v in movie_data.iteritems() if v) except: diff --git a/couchpotato/core/providers/info/themoviedb/main.py b/couchpotato/core/providers/info/themoviedb/main.py index a7901351..cb44f6d5 100644 --- a/couchpotato/core/providers/info/themoviedb/main.py +++ b/couchpotato/core/providers/info/themoviedb/main.py @@ -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,19 @@ 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: + actors.append({toUnicode(cast_item.name): toUnicode(cast_item.character)}) + images.append({'actor %s' % toUnicode(cast_item.name): self.getImage(cast_item, type = 'profile', size = 'original')}) + 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 +130,7 @@ class TheMovieDb(MovieProvider): 'plot': movie.overview, 'genres': genres, 'collection': getattr(movie.collection, 'name', None), + 'actors': actors } movie_data = dict((k, v) for k, v in movie_data.iteritems() if v) diff --git a/couchpotato/core/providers/metadata/xbmc/main.py b/couchpotato/core/providers/metadata/xbmc/main.py index 09e523aa..659139b4 100644 --- a/couchpotato/core/providers/metadata/xbmc/main.py +++ b/couchpotato/core/providers/metadata/xbmc/main.py @@ -89,10 +89,16 @@ 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, role_name in movie_info.get('actors', {}): + 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', []): From 1b5bc1fa05812e0e82ff5e8cd7656a8113a76a48 Mon Sep 17 00:00:00 2001 From: mano3m Date: Thu, 21 Nov 2013 00:43:17 +0100 Subject: [PATCH 05/10] [Metadata][XBMC] Add fileinfo to nfo Also fixed a int / int = int divide bug --- couchpotato/core/plugins/scanner/main.py | 2 +- .../core/providers/metadata/xbmc/main.py | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/couchpotato/core/plugins/scanner/main.py b/couchpotato/core/plugins/scanner/main.py index eb193ad8..24eb7ac7 100644 --- a/couchpotato/core/plugins/scanner/main.py +++ b/couchpotato/core/plugins/scanner/main.py @@ -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 diff --git a/couchpotato/core/providers/metadata/xbmc/main.py b/couchpotato/core/providers/metadata/xbmc/main.py index 659139b4..0d853dfe 100644 --- a/couchpotato/core/providers/metadata/xbmc/main.py +++ b/couchpotato/core/providers/metadata/xbmc/main.py @@ -139,6 +139,30 @@ class XBMC(MetaDataBase): 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 = ' ') From f0bde7316d4ac9e0b95e18b8617b7d1a608cc98d Mon Sep 17 00:00:00 2001 From: mano3m Date: Fri, 22 Nov 2013 13:07:53 +0100 Subject: [PATCH 06/10] [Metadata][XBMC] Update new actors to actor_roles --- couchpotato/core/providers/info/omdbapi/main.py | 6 +++++- couchpotato/core/providers/info/themoviedb/main.py | 13 ++++++++----- couchpotato/core/providers/metadata/xbmc/main.py | 4 +++- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/couchpotato/core/providers/info/omdbapi/main.py b/couchpotato/core/providers/info/omdbapi/main.py index c5db5eab..605dadf1 100755 --- a/couchpotato/core/providers/info/omdbapi/main.py +++ b/couchpotato/core/providers/info/omdbapi/main.py @@ -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': [{actor: ''} for actor in splitString(movie.get('Actors', ''))], + 'actor_roles': actors, } movie_data = dict((k, v) for k, v in movie_data.iteritems() if v) except: diff --git a/couchpotato/core/providers/info/themoviedb/main.py b/couchpotato/core/providers/info/themoviedb/main.py index cb44f6d5..cd957927 100644 --- a/couchpotato/core/providers/info/themoviedb/main.py +++ b/couchpotato/core/providers/info/themoviedb/main.py @@ -111,10 +111,13 @@ class TheMovieDb(MovieProvider): year = None # Gather actors data - actors = [] + actors = {} for cast_item in movie.cast: - actors.append({toUnicode(cast_item.name): toUnicode(cast_item.character)}) - images.append({'actor %s' % toUnicode(cast_item.name): self.getImage(cast_item, type = 'profile', size = 'original')}) + 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', @@ -130,7 +133,7 @@ class TheMovieDb(MovieProvider): 'plot': movie.overview, 'genres': genres, 'collection': getattr(movie.collection, 'name', None), - 'actors': actors + 'actor_roles': actors } movie_data = dict((k, v) for k, v in movie_data.iteritems() if v) @@ -154,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 diff --git a/couchpotato/core/providers/metadata/xbmc/main.py b/couchpotato/core/providers/metadata/xbmc/main.py index 0d853dfe..4c547c35 100644 --- a/couchpotato/core/providers/metadata/xbmc/main.py +++ b/couchpotato/core/providers/metadata/xbmc/main.py @@ -89,7 +89,9 @@ class XBMC(MetaDataBase): genres.text = toUnicode(genre) # Actors - for actor_name, role_name in movie_info.get('actors', {}): + 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) From 4553726423913972eed3ed73875ddfe7413367aa Mon Sep 17 00:00:00 2001 From: mano3m Date: Sat, 7 Dec 2013 15:07:41 +0100 Subject: [PATCH 07/10] [Notifications][XBMC] Add always do a full scan option to XBMC Fixes #2498 (at least partially) --- couchpotato/core/notifications/xbmc/__init__.py | 8 ++++++++ couchpotato/core/notifications/xbmc/main.py | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/couchpotato/core/notifications/xbmc/__init__.py b/couchpotato/core/notifications/xbmc/__init__.py index dafa0f63..04662e27 100644 --- a/couchpotato/core/notifications/xbmc/__init__.py +++ b/couchpotato/core/notifications/xbmc/__init__.py @@ -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, diff --git a/couchpotato/core/notifications/xbmc/main.py b/couchpotato/core/notifications/xbmc/main.py index dc185c41..9dac4979 100755 --- a/couchpotato/core/notifications/xbmc/main.py +++ b/couchpotato/core/notifications/xbmc/main.py @@ -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)) From 824ac86d18293a22e1b4bf79ac0c98fd68d7f63e Mon Sep 17 00:00:00 2001 From: mano3m Date: Sat, 7 Dec 2013 22:11:16 +0100 Subject: [PATCH 08/10] Fix fnmatch fnmatch does not accept regular expressions as presumed in 0c4851e43608ace7c5c6243486a8eb516619c75e See http://docs.python.org/2/library/fnmatch.html This patch actually completely broke tagging. All we need to do is make sure any [ or ] used is conbverted into [[] or []]. Fixes #2557 and #2362 --- couchpotato/core/helpers/variable.py | 3 +++ couchpotato/core/plugins/renamer/main.py | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/couchpotato/core/helpers/variable.py b/couchpotato/core/helpers/variable.py index 7d35b997..1cf1f484 100644 --- a/couchpotato/core/helpers/variable.py +++ b/couchpotato/core/helpers/variable.py @@ -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 diff --git a/couchpotato/core/plugins/renamer/main.py b/couchpotato/core/plugins/renamer/main.py index 3734845d..119d82bd 100755 --- a/couchpotato/core/plugins/renamer/main.py +++ b/couchpotato/core/plugins/renamer/main.py @@ -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 From 4db68e48870a54f14d21a3f90fdb26a6f9464da4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20K=C3=A5berg?= Date: Sun, 8 Dec 2013 13:07:17 +0100 Subject: [PATCH 09/10] update contributing --- contributing.md | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/contributing.md b/contributing.md index ef8546f0..d5db0b42 100644 --- a/contributing.md +++ b/contributing.md @@ -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 ;)** From 3b519aeac9d81a259e5e85123065ede7f0f5176c Mon Sep 17 00:00:00 2001 From: Ruud Date: Thu, 12 Dec 2013 19:58:55 +0100 Subject: [PATCH 10/10] nzbmegasearch returns redirected url. fix #2597 --- couchpotato/core/providers/nzb/newznab/main.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/couchpotato/core/providers/nzb/newznab/main.py b/couchpotato/core/providers/nzb/newznab/main.py index bd1b6c32..c1eed852 100644 --- a/couchpotato/core/providers/nzb/newznab/main.py +++ b/couchpotato/core/providers/nzb/newznab/main.py @@ -10,6 +10,7 @@ from urllib2 import HTTPError from urlparse import urlparse import time import traceback +import urllib2 log = CPLog(__name__) @@ -159,7 +160,15 @@ class Newznab(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: