You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

314 lines
9.5 KiB

from couchpotato import get_session
from couchpotato.api import addApiView
from couchpotato.core.event import fireEvent, fireEventAsync, addEvent
from couchpotato.core.helpers.encoding import toUnicode
from couchpotato.core.helpers.request import getParams, jsonified
from couchpotato.core.logger import CPLog
from couchpotato.core.plugins.base import Plugin
from couchpotato.core.settings.model import Movie, Library, LibraryTitle
from couchpotato.environment import Env
from sqlalchemy.orm import joinedload_all
from sqlalchemy.sql.expression import or_, asc, not_
from string import ascii_lowercase
from urllib import urlencode
log = CPLog(__name__)
class MoviePlugin(Plugin):
default_dict = {
'profile': {'types': {'quality': {}}},
'releases': {'status': {}, 'quality': {}, 'files':{}, 'info': {}},
'library': {'titles': {}, 'files':{}},
'files': {},
'status': {}
}
def __init__(self):
addApiView('movie.search', self.search)
addApiView('movie.list', self.listView)
addApiView('movie.refresh', self.refresh)
addApiView('movie.available_chars', self.charView)
addApiView('movie.add', self.addView)
addApiView('movie.edit', self.edit)
addApiView('movie.delete', self.delete)
addEvent('movie.add', self.add)
addEvent('movie.get', self.get)
addEvent('movie.list', self.list)
addEvent('movie.restatus', self.restatus)
def get(self, movie_id):
db = get_session()
m = db.query(Movie).filter_by(id = movie_id).first()
return m.to_dict(self.default_dict)
def list(self, status = ['active'], limit_offset = None, starts_with = None, search = None):
db = get_session()
# Make a list from string
if not isinstance(status, (list, tuple)):
status = [status]
q = db.query(Movie) \
.join(Movie.library, Library.titles) \
.options(joinedload_all('releases.status')) \
.options(joinedload_all('releases.quality')) \
.options(joinedload_all('releases.files')) \
.options(joinedload_all('releases.info')) \
.options(joinedload_all('library.titles')) \
.options(joinedload_all('library.files')) \
.options(joinedload_all('status')) \
.options(joinedload_all('files')) \
.filter(LibraryTitle.default == True) \
.filter(or_(*[Movie.status.has(identifier = s) for s in status]))
filter_or = []
if starts_with:
starts_with = toUnicode(starts_with.lower())
if starts_with in ascii_lowercase:
filter_or.append(LibraryTitle.simple_title.startswith(starts_with))
else:
ignore = []
for letter in ascii_lowercase:
ignore.append(LibraryTitle.simple_title.startswith(toUnicode(letter)))
filter_or.append(not_(or_(*ignore)))
if search:
filter_or.append(LibraryTitle.simple_title.like('%%' + search + '%%'))
if filter_or:
q = q.filter(or_(*filter_or))
q = q.order_by(asc(LibraryTitle.simple_title))
if limit_offset:
splt = limit_offset.split(',')
limit = splt[0]
offset = 0 if len(splt) is 1 else splt[1]
q = q.limit(limit).offset(offset)
results = q.all()
movies = []
for movie in results:
temp = movie.to_dict(self.default_dict)
movies.append(temp)
return movies
def availableChars(self, status = ['active']):
chars = ''
db = get_session()
# Make a list from string
if not isinstance(status, (list, tuple)):
status = [status]
q = db.query(Movie) \
.join(Movie.library, Library.titles) \
.options(joinedload_all('library.titles')) \
.filter(LibraryTitle.default == True) \
.filter(or_(*[Movie.status.has(identifier = s) for s in status]))
results = q.all()
for movie in results:
char = movie.library.titles[0].simple_title[0]
char = char if char in ascii_lowercase else '#'
if char not in chars:
chars += char
return chars
def listView(self):
params = getParams()
status = params.get('status', ['active'])
limit_offset = params.get('limit_offset', None)
starts_with = params.get('starts_with', None)
search = params.get('search', None)
movies = self.list(status = status, limit_offset = limit_offset, starts_with = starts_with, search = search)
return jsonified({
'success': True,
'empty': len(movies) == 0,
'movies': movies,
})
def charView(self):
params = getParams()
status = params.get('status', ['active'])
chars = self.availableChars(status)
return jsonified({
'success': True,
'empty': len(chars) == 0,
'chars': chars,
})
def refresh(self):
params = getParams()
db = get_session()
movie = db.query(Movie).filter_by(id = params.get('id')).first()
# Get current selected title
default_title = ''
for title in movie.library.titles:
if title.default: default_title = title.title
if movie:
#addEvent('library.update.after', )
fireEventAsync('library.update', identifier = movie.library.identifier, default_title = default_title, force = True)
fireEventAsync('searcher.single', movie.to_dict(self.default_dict))
return jsonified({
'success': True,
})
def search(self):
params = getParams()
cache_key = '%s/%s' % (__name__, urlencode(params))
movies = Env.get('cache').get(cache_key)
if not movies:
movies = fireEvent('movie.search', q = params.get('q'), merge = True)
Env.get('cache').set(cache_key, movies)
return jsonified({
'success': True,
'empty': len(movies) == 0 if movies else 0,
'movies': movies,
})
def add(self, params = {}, force_readd = True):
library = fireEvent('library.add', single = True, attrs = params, update_after = False)
# Status
status_active = fireEvent('status.add', 'active', single = True)
status_snatched = fireEvent('status.add', 'snatched', single = True)
default_profile = fireEvent('profile.default', single = True)
db = get_session()
m = db.query(Movie).filter_by(library_id = library.get('id')).first()
do_search = False
if not m:
m = Movie(
library_id = library.get('id'),
profile_id = params.get('profile_id', default_profile.get('id'))
)
db.add(m)
fireEvent('library.update', params.get('identifier'), default_title = params.get('title', ''))
do_search = True
elif force_readd:
# Clean snatched history
for release in m.releases:
if release.status_id == status_snatched.get('id'):
release.delete()
m.profile_id = params.get('profile_id', default_profile.get('id'))
else:
log.debug('Movie already exists, not updating: %s' % params)
if force_readd:
m.status_id = status_active.get('id')
db.commit()
movie_dict = m.to_dict(self.default_dict)
if force_readd or do_search:
fireEventAsync('searcher.single', movie_dict)
return movie_dict
def addView(self):
params = getParams()
movie_dict = self.add(params)
return jsonified({
'success': True,
'added': True,
'movie': movie_dict,
})
def edit(self):
params = getParams()
db = get_session()
m = db.query(Movie).filter_by(id = params.get('id')).first()
m.profile_id = params.get('profile_id')
# Default title
for title in m.library.titles:
title.default = params.get('default_title').lower() == title.title.lower()
db.commit()
fireEvent('movie.restatus', m.id)
movie_dict = m.to_dict(self.default_dict)
fireEventAsync('searcher.single', movie_dict)
return jsonified({
'success': True,
})
def delete(self):
params = getParams()
db = get_session()
status = fireEvent('status.add', 'deleted', single = True)
movie = db.query(Movie).filter_by(id = params.get('id')).first()
movie.status_id = status.get('id')
db.commit()
return jsonified({
'success': True,
})
def restatus(self, movie_id):
active_status = fireEvent('status.get', 'active', single = True)
done_status = fireEvent('status.get', 'done', single = True)
db = get_session()
m = db.query(Movie).filter_by(id = movie_id).first()
if not m.profile:
return
log.debug('Changing status for %s' % (m.library.titles[0].title))
move_to_wanted = True
for t in m.profile.types:
for release in m.releases:
if t.quality.identifier is release.quality.identifier and (release.status_id is done_status.get('id') and t.finish):
move_to_wanted = False
m.status_id = active_status.get('id') if move_to_wanted else done_status.get('id')
db.commit()