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.

315 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
14 years ago
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
14 years ago
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)
14 years ago
addApiView('movie.refresh', self.refresh)
addApiView('movie.available_chars', self.charView)
14 years ago
addApiView('movie.add', self.addView)
14 years ago
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)
14 years ago
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):
14 years ago
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,
})
14 years ago
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))
14 years ago
return jsonified({
'success': True,
})
def search(self):
14 years ago
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)
14 years ago
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()
14 years ago
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,
14 years ago
})
def edit(self):
params = getParams()
14 years ago
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()
14 years ago
fireEvent('movie.restatus', m.id)
movie_dict = m.to_dict(self.default_dict)
fireEventAsync('searcher.single', movie_dict)
return jsonified({
'success': True,
})
14 years ago
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')
14 years ago
db.commit()
return jsonified({
'success': True,
})
14 years ago
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()