diff --git a/couchpotato/core/media/movie/_base/main.py b/couchpotato/core/media/movie/_base/main.py index 3ca36ed..12eaf89 100644 --- a/couchpotato/core/media/movie/_base/main.py +++ b/couchpotato/core/media/movie/_base/main.py @@ -1,3 +1,4 @@ +import os from couchpotato import get_session from couchpotato.api import addApiView from couchpotato.core.event import fireEvent, fireEventAsync, addEvent @@ -70,6 +71,7 @@ class MovieBase(MovieTypeBase): 'params': { 'id': {'desc': 'Movie ID(s) you want to delete.', 'type': 'int (comma separated)'}, 'delete_from': {'desc': 'Delete movie from this page', 'type': 'string: all (default), wanted, manage'}, + 'with_files': {'desc': 'Delete the files as well', 'type': 'bool (true or false)'}, } }) @@ -461,18 +463,64 @@ class MovieBase(MovieTypeBase): ids = splitString(id) for movie_id in ids: - self.delete(movie_id, delete_from = kwargs.get('delete_from', 'all')) + self.delete(movie_id, delete_from = kwargs.get('delete_from', 'all'), with_files = kwargs.get('with_files')) return { 'success': True, } - def delete(self, movie_id, delete_from = None): + def deleteFiles(self, instance): + directories = dict() + + # Walk through all files in the Couch database + for file_ in instance.files: + # Add the directories and filename prefixes to a list so we can + # remove the directories and related files as well + directory = os.path.dirname(file_.path) + if directory not in directories: + directories[directory] = set() + directories[directory].add(os.path.splitext(file_.path)[0]) + + if os.path.isfile(file_.path): + try: + os.remove(file_.path) + log.info('Removed %s', file_.path) + except: + log.error('Unable to remove %s', file_.path) + + # Walk through the directories and file prefixes for removal if + # possible + for directory, prefixes in directories.iteritems(): + if os.path.isdir(directory): + + # If the files in the directory have the same name as the + # expected files (except for extensions and stuff), remove them + files = os.listdir(directory) + for file_ in files: + for prefix in prefixes: + if file_.startswith(prefix): + try: + os.remove(file_) + print 'rmoeving', file_ + log.info('Removed %s', file_) + except: + log.error('Unable to remove %s', file_) + + try: + os.rmdir(directory) + log.info('Removed %s', directory) + except: + log.error('Unable to remove %s', directory) + + def delete(self, movie_id, delete_from = None, with_files = False): db = get_session() movie = db.query(Media).filter_by(id = movie_id).first() if movie: + if with_files: + self.deleteFiles(movie) + deleted = False if delete_from == 'all': db.delete(movie) @@ -485,6 +533,9 @@ class MovieBase(MovieTypeBase): total_deleted = 0 new_movie_status = None for release in movie.releases: + if with_files: + self.deleteFiles(release) + if delete_from in ['wanted', 'snatched', 'late']: if release.status_id != done_status.get('id'): db.delete(release) diff --git a/couchpotato/core/media/movie/_base/static/movie.actions.js b/couchpotato/core/media/movie/_base/static/movie.actions.js index e3591f3..b81ab24 100644 --- a/couchpotato/core/media/movie/_base/static/movie.actions.js +++ b/couchpotato/core/media/movie/_base/static/movie.actions.js @@ -792,10 +792,27 @@ MA.Delete = new Class({ new Element('a.button.delete', { 'text': 'Delete ' + self.movie.title.get('text'), 'events': { - 'click': self.del.bind(self) + 'click': self.del.bind(self, false) } }) - ).inject(self.movie, 'top'); + ); + + /* Deleting files is only useful if it's already downloaded */ + if(self.movie.list.options.identifier == 'manage'){ + self.delete_container.adopt( + new Element('span', { + 'text': ' ' + }), + new Element('a.button.delete', { + 'text': '+ Files', + 'events': { + 'click': self.del.bind(self, true) + } + }) + ); + } + + self.delete_container.inject(self.movie, 'top'); } self.movie.slide('in', self.delete_container); @@ -810,7 +827,7 @@ MA.Delete = new Class({ self.movie.slide('out'); }, - del: function(e){ + del: function(withFiles, e){ (e).preventDefault(); var self = this; @@ -824,7 +841,8 @@ MA.Delete = new Class({ Api.request('movie.delete', { 'data': { 'id': self.movie.get('id'), - 'delete_from': self.movie.list.options.identifier + 'delete_from': self.movie.list.options.identifier, + 'with_files': !!withFiles }, 'onComplete': function(){ movie.set('tween', { @@ -840,7 +858,6 @@ MA.Delete = new Class({ ); self.callChain(); - } }); @@ -924,4 +941,4 @@ MA.Files = new Class({ self.movie.slide('in', self.options_container); }, -}); \ No newline at end of file +}); diff --git a/couchpotato/static/scripts/page/settings.js b/couchpotato/static/scripts/page/settings.js index d4c65e3..aa51619 100644 --- a/couchpotato/static/scripts/page/settings.js +++ b/couchpotato/static/scripts/page/settings.js @@ -1456,4 +1456,4 @@ Option.Combined = new Class({ self.saveCombined(); } -}); \ No newline at end of file +});