Merge branch 'refs/heads/develop'
This commit is contained in:
@@ -22,7 +22,7 @@ class BaseHandler(RequestHandler):
|
|||||||
username = Env.setting('username')
|
username = Env.setting('username')
|
||||||
password = Env.setting('password')
|
password = Env.setting('password')
|
||||||
|
|
||||||
if username or password:
|
if username and password:
|
||||||
return self.get_secure_cookie('user')
|
return self.get_secure_cookie('user')
|
||||||
else: # Login when no username or password are set
|
else: # Login when no username or password are set
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
from base64 import b16encode, b32decode
|
from base64 import b16encode, b32decode
|
||||||
from datetime import timedelta
|
|
||||||
from hashlib import sha1
|
|
||||||
import shutil
|
|
||||||
from couchpotato.core.helpers.encoding import ss
|
|
||||||
from rtorrent.err import MethodError
|
|
||||||
|
|
||||||
from bencode import bencode, bdecode
|
from bencode import bencode, bdecode
|
||||||
from couchpotato.core.downloaders.base import Downloader, StatusList
|
from couchpotato.core.downloaders.base import Downloader, StatusList
|
||||||
|
from couchpotato.core.helpers.encoding import ss
|
||||||
from couchpotato.core.logger import CPLog
|
from couchpotato.core.logger import CPLog
|
||||||
|
from datetime import timedelta
|
||||||
|
from hashlib import sha1
|
||||||
from rtorrent import RTorrent
|
from rtorrent import RTorrent
|
||||||
|
from rtorrent.err import MethodError
|
||||||
|
import shutil
|
||||||
|
|
||||||
log = CPLog(__name__)
|
log = CPLog(__name__)
|
||||||
|
|
||||||
|
|
||||||
class rTorrent(Downloader):
|
class rTorrent(Downloader):
|
||||||
|
|
||||||
protocol = ['torrent', 'torrent_magnet']
|
protocol = ['torrent', 'torrent_magnet']
|
||||||
rt = None
|
rt = None
|
||||||
|
|
||||||
@@ -194,7 +193,7 @@ class rTorrent(Downloader):
|
|||||||
if torrent is None:
|
if torrent is None:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
torrent.erase() # just removes the torrent, doesn't delete data
|
torrent.erase() # just removes the torrent, doesn't delete data
|
||||||
|
|
||||||
if delete_files:
|
if delete_files:
|
||||||
shutil.rmtree(item['folder'], True)
|
shutil.rmtree(item['folder'], True)
|
||||||
|
|||||||
@@ -118,7 +118,9 @@ class Manage(Plugin):
|
|||||||
fireEvent('movie.delete', movie_id = done_movie['id'], delete_from = 'all')
|
fireEvent('movie.delete', movie_id = done_movie['id'], delete_from = 'all')
|
||||||
else:
|
else:
|
||||||
|
|
||||||
for release in done_movie.get('releases', []):
|
releases = fireEvent('release.for_movie', id = done_movie.get('id'), single = True)
|
||||||
|
|
||||||
|
for release in releases:
|
||||||
if len(release.get('files', [])) == 0:
|
if len(release.get('files', [])) == 0:
|
||||||
fireEvent('release.delete', release['id'])
|
fireEvent('release.delete', release['id'])
|
||||||
else:
|
else:
|
||||||
@@ -129,9 +131,9 @@ class Manage(Plugin):
|
|||||||
break
|
break
|
||||||
|
|
||||||
# Check if there are duplicate releases (different quality) use the last one, delete the rest
|
# Check if there are duplicate releases (different quality) use the last one, delete the rest
|
||||||
if len(done_movie.get('releases', [])) > 1:
|
if len(releases) > 1:
|
||||||
used_files = {}
|
used_files = {}
|
||||||
for release in done_movie.get('releases', []):
|
for release in releases:
|
||||||
|
|
||||||
for release_file in release.get('files', []):
|
for release_file in release.get('files', []):
|
||||||
already_used = used_files.get(release_file['path'])
|
already_used = used_files.get(release_file['path'])
|
||||||
|
|||||||
@@ -37,13 +37,14 @@ class Release(Plugin):
|
|||||||
'id': {'type': 'id', 'desc': 'ID of the release object in release-table'}
|
'id': {'type': 'id', 'desc': 'ID of the release object in release-table'}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
addApiView('release.for_movie', self.forMovie, docs = {
|
addApiView('release.for_movie', self.forMovieView, docs = {
|
||||||
'desc': 'Returns all releases for a movie. Ordered by score(desc)',
|
'desc': 'Returns all releases for a movie. Ordered by score(desc)',
|
||||||
'params': {
|
'params': {
|
||||||
'id': {'type': 'id', 'desc': 'ID of the movie'}
|
'id': {'type': 'id', 'desc': 'ID of the movie'}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
addEvent('release.for_movie', self.forMovie)
|
||||||
addEvent('release.delete', self.delete)
|
addEvent('release.delete', self.delete)
|
||||||
addEvent('release.clean', self.clean)
|
addEvent('release.clean', self.clean)
|
||||||
|
|
||||||
@@ -216,7 +217,7 @@ class Release(Plugin):
|
|||||||
'success': False
|
'success': False
|
||||||
}
|
}
|
||||||
|
|
||||||
def forMovie(self, id = None, **kwargs):
|
def forMovie(self, id = None):
|
||||||
|
|
||||||
db = get_session()
|
db = get_session()
|
||||||
|
|
||||||
@@ -229,6 +230,12 @@ class Release(Plugin):
|
|||||||
releases = [r.to_dict({'info':{}, 'files':{}}) for r in releases_raw]
|
releases = [r.to_dict({'info':{}, 'files':{}}) for r in releases_raw]
|
||||||
releases = sorted(releases, key = lambda k: k['info'].get('score', 0), reverse = True)
|
releases = sorted(releases, key = lambda k: k['info'].get('score', 0), reverse = True)
|
||||||
|
|
||||||
|
return releases
|
||||||
|
|
||||||
|
def forMovieView(self, id = None, **kwargs):
|
||||||
|
|
||||||
|
releases = self.forMovie(id)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'releases': releases,
|
'releases': releases,
|
||||||
'success': True
|
'success': True
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from couchpotato.api import addApiView
|
|||||||
from couchpotato.core.event import fireEvent
|
from couchpotato.core.event import fireEvent
|
||||||
from couchpotato.core.helpers.variable import splitString
|
from couchpotato.core.helpers.variable import splitString
|
||||||
from couchpotato.core.plugins.base import Plugin
|
from couchpotato.core.plugins.base import Plugin
|
||||||
from couchpotato.core.settings.model import Movie
|
from couchpotato.core.settings.model import Movie, Library
|
||||||
from couchpotato.environment import Env
|
from couchpotato.environment import Env
|
||||||
from sqlalchemy.orm import joinedload_all
|
from sqlalchemy.orm import joinedload_all
|
||||||
from sqlalchemy.sql.expression import or_
|
from sqlalchemy.sql.expression import or_
|
||||||
@@ -20,6 +20,7 @@ class Suggestion(Plugin):
|
|||||||
|
|
||||||
movies = splitString(kwargs.get('movies', ''))
|
movies = splitString(kwargs.get('movies', ''))
|
||||||
ignored = splitString(kwargs.get('ignored', ''))
|
ignored = splitString(kwargs.get('ignored', ''))
|
||||||
|
seen = splitString(kwargs.get('seen', ''))
|
||||||
|
|
||||||
cached_suggestion = self.getCache('suggestion_cached')
|
cached_suggestion = self.getCache('suggestion_cached')
|
||||||
if cached_suggestion:
|
if cached_suggestion:
|
||||||
@@ -35,6 +36,8 @@ class Suggestion(Plugin):
|
|||||||
|
|
||||||
if not ignored or len(ignored) == 0:
|
if not ignored or len(ignored) == 0:
|
||||||
ignored = splitString(Env.prop('suggest_ignore', default = ''))
|
ignored = splitString(Env.prop('suggest_ignore', default = ''))
|
||||||
|
if not seen or len(seen) == 0:
|
||||||
|
movies.extend(splitString(Env.prop('suggest_seen', default = '')))
|
||||||
|
|
||||||
suggestions = fireEvent('movie.suggest', movies = movies, ignore = ignored, single = True)
|
suggestions = fireEvent('movie.suggest', movies = movies, ignore = ignored, single = True)
|
||||||
self.setCache('suggestion_cached', suggestions, timeout = 6048000) # Cache for 10 weeks
|
self.setCache('suggestion_cached', suggestions, timeout = 6048000) # Cache for 10 weeks
|
||||||
@@ -45,17 +48,21 @@ class Suggestion(Plugin):
|
|||||||
'suggestions': suggestions[:int(limit)]
|
'suggestions': suggestions[:int(limit)]
|
||||||
}
|
}
|
||||||
|
|
||||||
def ignoreView(self, imdb = None, limit = 6, remove_only = False, **kwargs):
|
def ignoreView(self, imdb = None, limit = 6, remove_only = False, mark_seen = False, **kwargs):
|
||||||
|
|
||||||
ignored = splitString(Env.prop('suggest_ignore', default = ''))
|
ignored = splitString(Env.prop('suggest_ignore', default = ''))
|
||||||
|
seen = splitString(Env.prop('suggest_seen', default = ''))
|
||||||
|
|
||||||
new_suggestions = []
|
new_suggestions = []
|
||||||
if imdb:
|
if imdb:
|
||||||
if not remove_only:
|
if mark_seen:
|
||||||
|
seen.append(imdb)
|
||||||
|
Env.prop('suggest_seen', ','.join(set(seen)))
|
||||||
|
elif not remove_only:
|
||||||
ignored.append(imdb)
|
ignored.append(imdb)
|
||||||
Env.prop('suggest_ignore', ','.join(set(ignored)))
|
Env.prop('suggest_ignore', ','.join(set(ignored)))
|
||||||
|
|
||||||
new_suggestions = self.updateSuggestionCache(ignore_imdb = imdb, limit = limit, ignored = ignored)
|
new_suggestions = self.updateSuggestionCache(ignore_imdb = imdb, limit = limit, ignored = ignored, seen = seen)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'result': True,
|
'result': True,
|
||||||
@@ -63,12 +70,13 @@ class Suggestion(Plugin):
|
|||||||
'suggestions': new_suggestions[limit - 1:limit]
|
'suggestions': new_suggestions[limit - 1:limit]
|
||||||
}
|
}
|
||||||
|
|
||||||
def updateSuggestionCache(self, ignore_imdb = None, limit = 6, ignored = None):
|
def updateSuggestionCache(self, ignore_imdb = None, limit = 6, ignored = None, seen = None):
|
||||||
|
|
||||||
# Combine with previous suggestion_cache
|
# Combine with previous suggestion_cache
|
||||||
cached_suggestion = self.getCache('suggestion_cached')
|
cached_suggestion = self.getCache('suggestion_cached')
|
||||||
new_suggestions = []
|
new_suggestions = []
|
||||||
ignored = [] if not ignored else ignored
|
ignored = [] if not ignored else ignored
|
||||||
|
seen = [] if not seen else seen
|
||||||
|
|
||||||
if ignore_imdb:
|
if ignore_imdb:
|
||||||
for cs in cached_suggestion:
|
for cs in cached_suggestion:
|
||||||
@@ -78,10 +86,15 @@ class Suggestion(Plugin):
|
|||||||
# Get new results and add them
|
# Get new results and add them
|
||||||
if len(new_suggestions) - 1 < limit:
|
if len(new_suggestions) - 1 < limit:
|
||||||
|
|
||||||
|
active_status, done_status = fireEvent('status.get', ['active', 'done'], single = True)
|
||||||
|
|
||||||
db = get_session()
|
db = get_session()
|
||||||
active_movies = db.query(Movie) \
|
active_movies = db.query(Movie) \
|
||||||
.filter(or_(*[Movie.status.has(identifier = s) for s in ['active', 'done']])).all()
|
.join(Library) \
|
||||||
movies = [x.library.identifier for x in active_movies]
|
.with_entities(Library.identifier) \
|
||||||
|
.filter(Movie.status_id.in_([active_status.get('id'), done_status.get('id')])).all()
|
||||||
|
movies = [x[0] for x in active_movies]
|
||||||
|
movies.extend(seen)
|
||||||
|
|
||||||
ignored.extend([x.get('imdb') for x in cached_suggestion])
|
ignored.extend([x.get('imdb') for x in cached_suggestion])
|
||||||
suggestions = fireEvent('movie.suggest', movies = movies, ignore = list(set(ignored)), single = True)
|
suggestions = fireEvent('movie.suggest', movies = movies, ignore = list(set(ignored)), single = True)
|
||||||
|
|||||||
@@ -105,7 +105,7 @@
|
|||||||
bottom: 10px;
|
bottom: 10px;
|
||||||
right: 10px;
|
right: 10px;
|
||||||
display: none;
|
display: none;
|
||||||
width: 120px;
|
width: 140px;
|
||||||
}
|
}
|
||||||
.suggestions .movie_result:hover .actions {
|
.suggestions .movie_result:hover .actions {
|
||||||
display: block;
|
display: block;
|
||||||
|
|||||||
@@ -26,6 +26,20 @@ var SuggestList = new Class({
|
|||||||
'onComplete': self.fill.bind(self)
|
'onComplete': self.fill.bind(self)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
'click:relay(a.eye-open)': function(e, el){
|
||||||
|
(e).stop();
|
||||||
|
|
||||||
|
$(el).getParent('.movie_result').destroy();
|
||||||
|
|
||||||
|
Api.request('suggestion.ignore', {
|
||||||
|
'data': {
|
||||||
|
'imdb': el.get('data-seen'),
|
||||||
|
'mark_seen': 1
|
||||||
|
},
|
||||||
|
'onComplete': self.fill.bind(self)
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).grab(
|
}).grab(
|
||||||
@@ -69,6 +83,10 @@ var SuggestList = new Class({
|
|||||||
new Element('a.delete.icon2', {
|
new Element('a.delete.icon2', {
|
||||||
'title': 'Don\'t suggest this movie again',
|
'title': 'Don\'t suggest this movie again',
|
||||||
'data-ignore': movie.imdb
|
'data-ignore': movie.imdb
|
||||||
|
}),
|
||||||
|
new Element('a.eye-open.icon2', {
|
||||||
|
'title': 'Seen it, like it, don\'t add',
|
||||||
|
'data-seen': movie.imdb
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
from couchpotato.core.event import addEvent
|
from couchpotato.core.event import addEvent
|
||||||
from couchpotato.core.helpers.encoding import simplifyString, toUnicode, ss
|
from couchpotato.core.helpers.encoding import simplifyString, toUnicode
|
||||||
from couchpotato.core.helpers.variable import md5
|
|
||||||
from couchpotato.core.logger import CPLog
|
from couchpotato.core.logger import CPLog
|
||||||
from couchpotato.core.providers.info.base import MovieProvider
|
from couchpotato.core.providers.info.base import MovieProvider
|
||||||
import tmdb3
|
import tmdb3
|
||||||
@@ -129,11 +128,9 @@ class TheMovieDb(MovieProvider):
|
|||||||
movie_data['titles'].append(movie.originaltitle)
|
movie_data['titles'].append(movie.originaltitle)
|
||||||
for alt in movie.alternate_titles:
|
for alt in movie.alternate_titles:
|
||||||
alt_name = alt.title
|
alt_name = alt.title
|
||||||
if alt_name and not alt_name in movie_data['titles'] and alt_name.lower() != 'none' and alt_name is not None:
|
if alt_name and alt_name not in movie_data['titles'] and alt_name.lower() != 'none' and alt_name is not None:
|
||||||
movie_data['titles'].append(alt_name)
|
movie_data['titles'].append(alt_name)
|
||||||
|
|
||||||
movie_data['titles'] = list(set(movie_data['titles']))
|
|
||||||
|
|
||||||
# Cache movie parsed
|
# Cache movie parsed
|
||||||
self.setCache(cache_key, movie_data)
|
self.setCache(cache_key, movie_data)
|
||||||
|
|
||||||
@@ -143,7 +140,7 @@ class TheMovieDb(MovieProvider):
|
|||||||
|
|
||||||
image_url = ''
|
image_url = ''
|
||||||
try:
|
try:
|
||||||
image_url = getattr(movie, type).geturl(size='original')
|
image_url = getattr(movie, type).geturl(size = 'original')
|
||||||
except:
|
except:
|
||||||
log.debug('Failed getting %s.%s for "%s"', (type, size, movie.title))
|
log.debug('Failed getting %s.%s for "%s"', (type, size, movie.title))
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -52,7 +52,7 @@ APP_PATH=${CP_HOME-/opt/couchpotato/}
|
|||||||
DATA_DIR=${CP_DATA-/var/couchpotato}
|
DATA_DIR=${CP_DATA-/var/couchpotato}
|
||||||
|
|
||||||
# Path to store PID file
|
# Path to store PID file
|
||||||
PID_FILE=${CP_PID_FILE-/var/run/couchpotato.pid}
|
PID_FILE=${CP_PIDFILE-/var/run/couchpotato.pid}
|
||||||
|
|
||||||
# path to python bin
|
# path to python bin
|
||||||
DAEMON=${PYTHON_BIN-/usr/bin/python}
|
DAEMON=${PYTHON_BIN-/usr/bin/python}
|
||||||
|
|||||||
Reference in New Issue
Block a user