nosql
This commit is contained in:
1 parent
99252074be
commit
a609b401c4
17 files changed
+313
-392
No files matched your search
@@ -1,4 +1,4 @@
|
|||||||
CouchPotato Server
|
CouchPotato
|
||||||
=====
|
=====
|
||||||
|
|
||||||
CouchPotato (CP) is an automatic NZB and torrent downloader. You can keep a "movies I want"-list and it will search for NZBs/torrents of these movies every X hours.
|
CouchPotato (CP) is an automatic NZB and torrent downloader. You can keep a "movies I want"-list and it will search for NZBs/torrents of these movies every X hours.
|
||||||
@@ -7,7 +7,7 @@ Once a movie is found, it will send it to SABnzbd or download the torrent to a s
|
|||||||
|
|
||||||
## Running from Source
|
## Running from Source
|
||||||
|
|
||||||
CouchPotatoServer can be run from source. This will use *git* as updater, so make sure that is installed also.
|
CouchPotatoServer can be run from source. This will use *git* as updater, so make sure that is installed.
|
||||||
|
|
||||||
Windows, see [the CP forum](http://couchpota.to/forum/showthread.php?tid=14) for more details:
|
Windows, see [the CP forum](http://couchpota.to/forum/showthread.php?tid=14) for more details:
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
from itertools import izip
|
from itertools import izip
|
||||||
|
from string import ascii_letters
|
||||||
from CodernityDB.hash_index import HashIndex
|
from CodernityDB.hash_index import HashIndex
|
||||||
from CodernityDB.tree_index import MultiTreeBasedIndex, TreeBasedIndex
|
from CodernityDB.tree_index import MultiTreeBasedIndex, TreeBasedIndex
|
||||||
from hashlib import md5
|
from hashlib import md5
|
||||||
|
from couchpotato.core.helpers.encoding import toUnicode, simplifyString
|
||||||
|
|
||||||
|
|
||||||
class MediaIMDBIndex(HashIndex):
|
class MediaIMDBIndex(HashIndex):
|
||||||
@@ -22,13 +24,13 @@ class MediaIMDBIndex(HashIndex):
|
|||||||
|
|
||||||
return db.get('id', media_id)
|
return db.get('id', media_id)
|
||||||
|
|
||||||
def run_with_status(self, db, status = []):
|
def run_with_status(self, db, status = [], with_doc = True):
|
||||||
|
|
||||||
status = list(status if isinstance(status, (list, tuple)) else [status])
|
status = list(status if isinstance(status, (list, tuple)) else [status])
|
||||||
|
|
||||||
for s in status:
|
for s in status:
|
||||||
for ms in db.get_many('media_status', s, with_doc = True):
|
for ms in db.get_many('media_status', s, with_doc = with_doc):
|
||||||
yield ms['doc']
|
yield ms['doc'] if with_doc else ms
|
||||||
|
|
||||||
|
|
||||||
class MediaStatusIndex(TreeBasedIndex):
|
class MediaStatusIndex(TreeBasedIndex):
|
||||||
@@ -45,31 +47,46 @@ class MediaStatusIndex(TreeBasedIndex):
|
|||||||
return md5(data.get('status')).hexdigest(), None
|
return md5(data.get('status')).hexdigest(), None
|
||||||
|
|
||||||
|
|
||||||
class TitleIndex(MultiTreeBasedIndex):
|
class MediaTypeIndex(TreeBasedIndex):
|
||||||
|
|
||||||
custom_header = """from CodernityDB.tree_index import MultiTreeBasedIndex
|
|
||||||
from itertools import izip"""
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
kwargs['key_format'] = '32s'
|
kwargs['key_format'] = '32s'
|
||||||
super(TitleIndex, self).__init__(*args, **kwargs)
|
super(MediaTypeIndex, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def make_key(self, key):
|
||||||
|
return md5(key).hexdigest()
|
||||||
|
|
||||||
|
def make_key_value(self, data):
|
||||||
|
if data.get('_t') == 'media' and data.get('type'):
|
||||||
|
return md5(data.get('type')).hexdigest(), None
|
||||||
|
|
||||||
|
|
||||||
|
class TitleSearchIndex(MultiTreeBasedIndex):
|
||||||
|
|
||||||
|
custom_header = """from CodernityDB.tree_index import MultiTreeBasedIndex
|
||||||
|
from itertools import izip
|
||||||
|
from couchpotato.core.helpers.encoding import simplifyString"""
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
kwargs['key_format'] = '32s'
|
||||||
|
super(TitleSearchIndex, self).__init__(*args, **kwargs)
|
||||||
self.__l = kwargs.get('w_len', 2)
|
self.__l = kwargs.get('w_len', 2)
|
||||||
|
|
||||||
def make_key_value(self, data):
|
def make_key_value(self, data):
|
||||||
|
|
||||||
if data.get('_t') == 'title' and len(data.get('title', '')) > 0:
|
if data.get('_t') == 'media' and len(data.get('title', '')) > 0:
|
||||||
|
|
||||||
out = set()
|
out = set()
|
||||||
title = data.get('title').lower()
|
title = str(simplifyString(data.get('title').lower()))
|
||||||
l = self.__l
|
l = self.__l
|
||||||
max_l = len(title)
|
max_l = len(title)
|
||||||
for x in xrange(l - 1, max_l):
|
for x in xrange(l - 1, max_l):
|
||||||
m = (title, )
|
m = (title, )
|
||||||
for y in xrange(0, x):
|
for y in xrange(0, x):
|
||||||
m += (title[y + 1:],)
|
m += (title[y + 1:],)
|
||||||
out.update(set(''.join(x).rjust(32, '_').lower() for x in izip(*m))) #ignore import error
|
out.update(set(''.join(x).rjust(32, '_').lower() for x in izip(*m)))
|
||||||
|
|
||||||
return out, {'media_id': data.get('media_id')}
|
return out, None
|
||||||
|
|
||||||
def make_key(self, key):
|
def make_key(self, key):
|
||||||
return key.rjust(32, '_').lower()
|
return key.rjust(32, '_').lower()
|
||||||
@@ -87,3 +104,64 @@ class YearIndex(TreeBasedIndex):
|
|||||||
def make_key_value(self, data):
|
def make_key_value(self, data):
|
||||||
if data.get('_t') == 'media' and data.get('year') is not None:
|
if data.get('_t') == 'media' and data.get('year') is not None:
|
||||||
return data['year'], None
|
return data['year'], None
|
||||||
|
|
||||||
|
|
||||||
|
class TitleIndex(TreeBasedIndex):
|
||||||
|
|
||||||
|
custom_header = """from CodernityDB.tree_index import TreeBasedIndex
|
||||||
|
from string import ascii_letters
|
||||||
|
from couchpotato.core.helpers.encoding import toUnicode, simplifyString"""
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
kwargs['key_format'] = '32s'
|
||||||
|
super(TitleIndex, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def make_key(self, key):
|
||||||
|
return self.simplify(key)
|
||||||
|
|
||||||
|
def make_key_value(self, data):
|
||||||
|
if data.get('_t') == 'media' and data.get('title') is not None:
|
||||||
|
return self.simplify(data['title']), None
|
||||||
|
|
||||||
|
def simplify(self, title):
|
||||||
|
|
||||||
|
title = toUnicode(title)
|
||||||
|
|
||||||
|
nr_prefix = '' if title[0] in ascii_letters else '#'
|
||||||
|
title = simplifyString(title)
|
||||||
|
|
||||||
|
for prefix in ['the ']:
|
||||||
|
if prefix == title[:len(prefix)]:
|
||||||
|
title = title[len(prefix):]
|
||||||
|
break
|
||||||
|
|
||||||
|
return str(nr_prefix + title).ljust(32, '_')[:32]
|
||||||
|
|
||||||
|
|
||||||
|
class StartsWithIndex(TreeBasedIndex):
|
||||||
|
|
||||||
|
custom_header = """from CodernityDB.tree_index import TreeBasedIndex
|
||||||
|
from string import ascii_letters
|
||||||
|
from couchpotato.core.helpers.encoding import toUnicode, simplifyString"""
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
kwargs['key_format'] = '1s'
|
||||||
|
super(StartsWithIndex, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def make_key(self, key):
|
||||||
|
return self.first(key)
|
||||||
|
|
||||||
|
def make_key_value(self, data):
|
||||||
|
if data.get('_t') == 'media' and data.get('title') is not None:
|
||||||
|
return self.first(data['title']), None
|
||||||
|
|
||||||
|
def first(self, title):
|
||||||
|
title = toUnicode(title)
|
||||||
|
title = simplifyString(title)
|
||||||
|
|
||||||
|
for prefix in ['the ']:
|
||||||
|
if prefix == title[:len(prefix)]:
|
||||||
|
title = title[len(prefix):]
|
||||||
|
break
|
||||||
|
|
||||||
|
return str(title[0] if title[0] in ascii_letters else '#').lower()
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
import traceback
|
import traceback
|
||||||
import time
|
|
||||||
from couchpotato import get_session, tryInt, get_db
|
from couchpotato import get_session, tryInt, get_db
|
||||||
from couchpotato.api import addApiView
|
from couchpotato.api import addApiView
|
||||||
from couchpotato.core.event import fireEvent, fireEventAsync, addEvent
|
from couchpotato.core.event import fireEvent, fireEventAsync, addEvent
|
||||||
from couchpotato.core.helpers.variable import mergeDicts, splitString, getImdb, getTitle
|
from couchpotato.core.helpers.encoding import toUnicode
|
||||||
|
from couchpotato.core.helpers.variable import splitString, getImdb, getTitle
|
||||||
from couchpotato.core.logger import CPLog
|
from couchpotato.core.logger import CPLog
|
||||||
from couchpotato.core.media import MediaBase
|
from couchpotato.core.media import MediaBase
|
||||||
from .index import MediaIMDBIndex, TitleIndex, MediaStatusIndex, YearIndex
|
from .index import MediaIMDBIndex, MediaStatusIndex, YearIndex, MediaTypeIndex, TitleSearchIndex, TitleIndex, StartsWithIndex
|
||||||
from couchpotato.core.settings.model import Library, LibraryTitle, Release, \
|
from couchpotato.core.settings.model import Media
|
||||||
Media
|
|
||||||
from string import ascii_lowercase
|
from string import ascii_lowercase
|
||||||
|
|
||||||
log = CPLog(__name__)
|
log = CPLog(__name__)
|
||||||
@@ -61,10 +60,10 @@ class MediaPlugin(MediaBase):
|
|||||||
|
|
||||||
addEvent('database.setup', self.databaseSetup)
|
addEvent('database.setup', self.databaseSetup)
|
||||||
|
|
||||||
addEvent('app.load', self.addSingleRefreshView)
|
addEvent('app.load', self.addSingleRefreshView, priority = 100)
|
||||||
addEvent('app.load', self.addSingleListView)
|
addEvent('app.load', self.addSingleListView, priority = 100)
|
||||||
addEvent('app.load', self.addSingleCharView)
|
addEvent('app.load', self.addSingleCharView, priority = 100)
|
||||||
addEvent('app.load', self.addSingleDeleteView)
|
addEvent('app.load', self.addSingleDeleteView, priority = 100)
|
||||||
|
|
||||||
addEvent('media.get', self.get)
|
addEvent('media.get', self.get)
|
||||||
addEvent('media.list', self.list)
|
addEvent('media.list', self.list)
|
||||||
@@ -84,10 +83,10 @@ class MediaPlugin(MediaBase):
|
|||||||
|
|
||||||
# Title index
|
# Title index
|
||||||
try:
|
try:
|
||||||
db.add_index(TitleIndex(db.path, 'media_title'))
|
db.add_index(TitleSearchIndex(db.path, 'media_search_title'))
|
||||||
except:
|
except:
|
||||||
log.debug('Index already exists')
|
log.debug('Index already exists')
|
||||||
db.edit_index(TitleIndex(db.path, 'media_title'))
|
db.edit_index(TitleSearchIndex(db.path, 'media_search_title'))
|
||||||
|
|
||||||
# Status index
|
# Status index
|
||||||
try:
|
try:
|
||||||
@@ -96,11 +95,31 @@ class MediaPlugin(MediaBase):
|
|||||||
log.debug('Index already exists')
|
log.debug('Index already exists')
|
||||||
db.edit_index(MediaStatusIndex(db.path, 'media_status'))
|
db.edit_index(MediaStatusIndex(db.path, 'media_status'))
|
||||||
|
|
||||||
# Year index
|
# Type index
|
||||||
try: db.add_index(YearIndex(db.path, 'year'))
|
try:
|
||||||
|
db.add_index(MediaTypeIndex(db.path, 'media_by_type'))
|
||||||
except:
|
except:
|
||||||
log.debug('Index already exists')
|
log.debug('Index already exists')
|
||||||
db.edit_index(YearIndex(db.path, 'year'))
|
db.edit_index(MediaTypeIndex(db.path, 'media_by_type'))
|
||||||
|
|
||||||
|
# Year index
|
||||||
|
try: db.add_index(YearIndex(db.path, 'media_year'))
|
||||||
|
except:
|
||||||
|
log.debug('Index already exists')
|
||||||
|
db.edit_index(YearIndex(db.path, 'media_year'))
|
||||||
|
|
||||||
|
# Title index
|
||||||
|
try: db.add_index(TitleIndex(db.path, 'media_title'))
|
||||||
|
except:
|
||||||
|
log.debug('Index already exists')
|
||||||
|
db.edit_index(TitleIndex(db.path, 'media_title'))
|
||||||
|
|
||||||
|
# Startswith index
|
||||||
|
try: db.add_index(StartsWithIndex(db.path, 'media_startswith'))
|
||||||
|
except:
|
||||||
|
log.debug('Index already exists')
|
||||||
|
db.edit_index(StartsWithIndex(db.path, 'media_startswith'))
|
||||||
|
|
||||||
|
|
||||||
def refresh(self, id = '', **kwargs):
|
def refresh(self, id = '', **kwargs):
|
||||||
handlers = []
|
handlers = []
|
||||||
@@ -112,7 +131,7 @@ class MediaPlugin(MediaBase):
|
|||||||
if refresh_handler:
|
if refresh_handler:
|
||||||
handlers.append(refresh_handler)
|
handlers.append(refresh_handler)
|
||||||
|
|
||||||
fireEvent('notify.frontend', type = 'media.busy', data = {'id': [tryInt(x) for x in ids]})
|
fireEvent('notify.frontend', type = 'media.busy', data = {'id': ids})
|
||||||
fireEventAsync('schedule.queue', handlers = handlers)
|
fireEventAsync('schedule.queue', handlers = handlers)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -124,8 +143,9 @@ class MediaPlugin(MediaBase):
|
|||||||
try:
|
try:
|
||||||
media = get_db().get('id', media_id)
|
media = get_db().get('id', media_id)
|
||||||
|
|
||||||
|
|
||||||
default_title = getTitle(media)
|
default_title = getTitle(media)
|
||||||
event = 'library.update.%s' % media.get('type')
|
event = '%s.update_info' % media.get('type')
|
||||||
|
|
||||||
def handler():
|
def handler():
|
||||||
fireEvent(event, identifier = media.get('identifier'), default_title = default_title, on_complete = self.createOnComplete(media_id))
|
fireEvent(event, identifier = media.get('identifier'), default_title = default_title, on_complete = self.createOnComplete(media_id))
|
||||||
@@ -172,8 +192,6 @@ class MediaPlugin(MediaBase):
|
|||||||
|
|
||||||
db = get_db()
|
db = get_db()
|
||||||
|
|
||||||
start = time.time()
|
|
||||||
|
|
||||||
# Make a list from string
|
# Make a list from string
|
||||||
if status and not isinstance(status, (list, tuple)):
|
if status and not isinstance(status, (list, tuple)):
|
||||||
status = [status]
|
status = [status]
|
||||||
@@ -183,125 +201,73 @@ class MediaPlugin(MediaBase):
|
|||||||
types = [types]
|
types = [types]
|
||||||
|
|
||||||
# query media ids
|
# query media ids
|
||||||
all_media_ids = set([x['_id'] for x in db.all('media')])
|
if types:
|
||||||
|
all_media_ids = set()
|
||||||
|
for media_type in types:
|
||||||
|
all_media_ids = all_media_ids.union(set([x['_id'] for x in db.get_many('media_by_type', media_type)]))
|
||||||
|
else:
|
||||||
|
all_media_ids = set([x['_id'] for x in db.all('media')])
|
||||||
|
|
||||||
media_ids = all_media_ids
|
media_ids = all_media_ids
|
||||||
filter_by = {}
|
filter_by = {}
|
||||||
|
|
||||||
# Filter on movie status
|
# Filter on movie status
|
||||||
if status and len(status) > 0:
|
if status and len(status) > 0:
|
||||||
filter_by['media_status'] = set()
|
filter_by['media_status'] = set()
|
||||||
for media_status in db.run('media', 'with_status', status):
|
for media_status in db.run('media', 'with_status', status, with_doc = False):
|
||||||
filter_by['media_status'].add(media_status.get('_id'))
|
filter_by['media_status'].add(media_status.get('_id'))
|
||||||
|
|
||||||
# Filter on release status
|
# Filter on release status
|
||||||
if release_status and len(release_status) > 0:
|
if release_status and len(release_status) > 0:
|
||||||
filter_by['release_status'] = set()
|
filter_by['release_status'] = set()
|
||||||
for release_status in db.run('release', 'with_status', release_status):
|
for release_status in db.run('release', 'with_status', release_status, with_doc = False):
|
||||||
filter_by['release_status'].add(release_status.get('media_id'))
|
filter_by['release_status'].add(release_status.get('media_id'))
|
||||||
|
|
||||||
|
# Add search filters
|
||||||
|
if starts_with:
|
||||||
|
filter_by['starts_with'] = set()
|
||||||
|
starts_with = toUnicode(starts_with.lower())[0]
|
||||||
|
starts_with = starts_with if starts_with in ascii_lowercase else '#'
|
||||||
|
filter_by['starts_with'] = [x['_id'] for x in db.get_many('media_startswith', starts_with)]
|
||||||
|
|
||||||
|
# Filter with search query
|
||||||
|
if search:
|
||||||
|
filter_by['search'] = [x['_id'] for x in db.get_many('media_search_title', search)]
|
||||||
|
|
||||||
# Filter by combining ids
|
# Filter by combining ids
|
||||||
for x in filter_by:
|
for x in filter_by:
|
||||||
media_ids = media_ids & filter_by[x]
|
media_ids = [n for n in media_ids if n in filter_by[x]]
|
||||||
|
|
||||||
# Filter on type
|
|
||||||
# if types and len(types) > 0:
|
|
||||||
# try: q = q.filter(Media.type.in_(types))
|
|
||||||
# except: pass
|
|
||||||
|
|
||||||
# Only join when searching / ordering
|
|
||||||
# if starts_with or search or order != 'release_order':
|
|
||||||
# q = q.join(Media.library, Library.titles) \
|
|
||||||
# .filter(LibraryTitle.default == True)
|
|
||||||
|
|
||||||
# Add search filters
|
|
||||||
# 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:
|
|
||||||
search_ids = db.get_many('media_title', search)
|
|
||||||
for search_id in search_ids:
|
|
||||||
print search_id
|
|
||||||
|
|
||||||
#if len(filter_or) > 0:
|
|
||||||
# pass #q = q.filter(or_(*filter_or))
|
|
||||||
|
|
||||||
total_count = len(media_ids)
|
total_count = len(media_ids)
|
||||||
if total_count == 0:
|
if total_count == 0:
|
||||||
return 0, []
|
return 0, []
|
||||||
|
|
||||||
# if order == 'release_order':
|
if limit_offset:
|
||||||
# q = q.order_by(desc(Release.last_edit))
|
splt = splitString(limit_offset) if isinstance(limit_offset, (str, unicode)) else limit_offset
|
||||||
# else:
|
limit = tryInt(splt[0])
|
||||||
# q = q.order_by(asc(LibraryTitle.simple_title))
|
offset = tryInt(0 if len(splt) is 1 else splt[1])
|
||||||
|
start = offset * limit
|
||||||
|
end = start + limit
|
||||||
|
media_ids = media_ids[start:end]
|
||||||
|
|
||||||
# if limit_offset:
|
# List movies based on title order
|
||||||
# splt = splitString(limit_offset) if isinstance(limit_offset, (str, unicode)) else limit_offset
|
|
||||||
# limit = splt[0]
|
|
||||||
# offset = 0 if len(splt) is 1 else splt[1]
|
|
||||||
# q = q.limit(limit).offset(offset)
|
|
||||||
|
|
||||||
# Get all media_ids in sorted order
|
|
||||||
# media_ids = [m.id for m in q.all()]
|
|
||||||
|
|
||||||
# List release statuses
|
|
||||||
# releases = db.query(Release) \
|
|
||||||
# .filter(Release.movie_id.in_(media_ids)) \
|
|
||||||
# .all()
|
|
||||||
|
|
||||||
# release_statuses = dict((m, set()) for m in media_ids)
|
|
||||||
# releases_count = dict((m, 0) for m in media_ids)
|
|
||||||
# for release in releases:
|
|
||||||
# release_statuses[release.movie_id].add('%d,%d' % (release.status_id, release.quality_id))
|
|
||||||
# releases_count[release.movie_id] += 1
|
|
||||||
|
|
||||||
# Get main movie data
|
|
||||||
# q2 = db.query(Media) \
|
|
||||||
# .options(joinedload_all('library.titles')) \
|
|
||||||
# .options(joinedload_all('library.files')) \
|
|
||||||
# .options(joinedload_all('status')) \
|
|
||||||
# .options(joinedload_all('files'))
|
|
||||||
|
|
||||||
# q2 = q2.filter(Media.id.in_(media_ids))
|
|
||||||
|
|
||||||
# results = q2.all()
|
|
||||||
|
|
||||||
# Create dict by movie id
|
|
||||||
# medias = {}
|
|
||||||
# for media in media_ids:
|
|
||||||
# movie_dict[movie.id] = movie
|
|
||||||
|
|
||||||
# List movies based on media_ids order
|
|
||||||
medias = []
|
medias = []
|
||||||
for media_id in media_ids:
|
for m in db.all('media_title'):
|
||||||
|
media_id = m['_id']
|
||||||
|
if media_id not in media_ids: continue
|
||||||
|
|
||||||
media = db.run('media', 'to_dict', media_id, {
|
media = db.run('media', 'to_dict', media_id)
|
||||||
'library': {'titles': {}, 'files': {}},
|
|
||||||
'files': {},
|
|
||||||
})
|
|
||||||
|
|
||||||
media['releases'] = []
|
media['releases'] = []
|
||||||
for r in db.get_many('release', media_id, with_doc = True):
|
for r in db.get_many('release', media_id, with_doc = True):
|
||||||
media['releases'].append(r)
|
media['releases'].append(r['doc'])
|
||||||
|
|
||||||
# Merge releases with movie dict
|
# Merge releases with movie dict
|
||||||
medias.append(media)
|
medias.append(media)
|
||||||
# medias.append(mergeDicts(movie_dict[media_id].to_dict({
|
|
||||||
# 'library': {'titles': {}, 'files': {}},
|
|
||||||
# 'files': {},
|
|
||||||
# }), {
|
|
||||||
# 'releases': releases,
|
|
||||||
# 'releases_count': releases_count.get(media_id),
|
|
||||||
# }))
|
|
||||||
|
|
||||||
print time.time() - start
|
# remove from media ids
|
||||||
|
media_ids.remove(media_id)
|
||||||
|
if len(media_ids) == 0: break
|
||||||
|
|
||||||
return total_count, medias
|
return total_count, medias
|
||||||
|
|
||||||
@@ -341,63 +307,52 @@ class MediaPlugin(MediaBase):
|
|||||||
|
|
||||||
def availableChars(self, types = None, status = None, release_status = None):
|
def availableChars(self, types = None, status = None, release_status = None):
|
||||||
|
|
||||||
types = types or []
|
db = get_db()
|
||||||
status = status or []
|
|
||||||
release_status = release_status or []
|
|
||||||
|
|
||||||
db = get_session()
|
|
||||||
|
|
||||||
# Make a list from string
|
# Make a list from string
|
||||||
if not isinstance(status, (list, tuple)):
|
if status and not isinstance(status, (list, tuple)):
|
||||||
status = [status]
|
status = [status]
|
||||||
if release_status and not isinstance(release_status, (list, tuple)):
|
if release_status and not isinstance(release_status, (list, tuple)):
|
||||||
release_status = [release_status]
|
release_status = [release_status]
|
||||||
if types and not isinstance(types, (list, tuple)):
|
if types and not isinstance(types, (list, tuple)):
|
||||||
types = [types]
|
types = [types]
|
||||||
|
|
||||||
q = db.query(Media)
|
# query media ids
|
||||||
|
if types:
|
||||||
|
all_media_ids = set()
|
||||||
|
for media_type in types:
|
||||||
|
all_media_ids = all_media_ids.union(set([x['_id'] for x in db.get_many('media_by_type', media_type)]))
|
||||||
|
else:
|
||||||
|
all_media_ids = set([x['_id'] for x in db.all('media')])
|
||||||
|
|
||||||
|
media_ids = all_media_ids
|
||||||
|
filter_by = {}
|
||||||
|
|
||||||
# Filter on movie status
|
# Filter on movie status
|
||||||
if status and len(status) > 0:
|
if status and len(status) > 0:
|
||||||
statuses = fireEvent('status.get', status, single = len(release_status) > 1)
|
filter_by['media_status'] = set()
|
||||||
statuses = [s.get('id') for s in statuses]
|
for media_status in db.run('media', 'with_status', status, with_doc = False):
|
||||||
|
filter_by['media_status'].add(media_status.get('_id'))
|
||||||
q = q.filter(Media.status_id.in_(statuses))
|
|
||||||
|
|
||||||
# Filter on release status
|
# Filter on release status
|
||||||
if release_status and len(release_status) > 0:
|
if release_status and len(release_status) > 0:
|
||||||
|
filter_by['release_status'] = set()
|
||||||
|
for release_status in db.run('release', 'with_status', release_status, with_doc = False):
|
||||||
|
filter_by['release_status'].add(release_status.get('media_id'))
|
||||||
|
|
||||||
statuses = fireEvent('status.get', release_status, single = len(release_status) > 1)
|
# Filter by combining ids
|
||||||
statuses = [s.get('id') for s in statuses]
|
for x in filter_by:
|
||||||
|
media_ids = [n for n in media_ids if n in filter_by[x]]
|
||||||
q = q.join(Media.releases) \
|
|
||||||
.filter(Release.status_id.in_(statuses))
|
|
||||||
|
|
||||||
# Filter on type
|
|
||||||
if types and len(types) > 0:
|
|
||||||
try: q = q.filter(Media.type.in_(types))
|
|
||||||
except: pass
|
|
||||||
|
|
||||||
q = q.join(Library, LibraryTitle) \
|
|
||||||
.with_entities(LibraryTitle.simple_title) \
|
|
||||||
.filter(LibraryTitle.default == True)
|
|
||||||
|
|
||||||
titles = q.all()
|
|
||||||
|
|
||||||
chars = set()
|
chars = set()
|
||||||
for title in titles:
|
for x in db.all('media_startswith'):
|
||||||
try:
|
if x['_id'] in media_ids:
|
||||||
char = title[0][0]
|
chars.add(x['key'])
|
||||||
char = char if char in ascii_lowercase else '#'
|
|
||||||
chars.add(str(char))
|
|
||||||
except:
|
|
||||||
log.error('Failed getting title for %s', title.libraries_id)
|
|
||||||
|
|
||||||
if len(chars) == 25:
|
if len(chars) == 25:
|
||||||
break
|
break
|
||||||
|
|
||||||
pass #db.close()
|
return list(chars)
|
||||||
return ''.join(sorted(chars))
|
|
||||||
|
|
||||||
def charView(self, **kwargs):
|
def charView(self, **kwargs):
|
||||||
|
|
||||||
@@ -487,32 +442,30 @@ class MediaPlugin(MediaBase):
|
|||||||
def restatus(self, media_id):
|
def restatus(self, media_id):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
db = get_session()
|
db = get_db()
|
||||||
|
|
||||||
m = db.query(Media).filter_by(id = media_id).first()
|
m = db.get('id', media_id)
|
||||||
if not m or len(m.library.titles) == 0:
|
|
||||||
log.debug('Can\'t restatus movie, doesn\'t seem to exist.')
|
|
||||||
return False
|
|
||||||
|
|
||||||
log.debug('Changing status for %s', m.library.titles[0].title)
|
log.debug('Changing status for %s', getTitle(m))
|
||||||
if not m['profile_id']:
|
if not m['profile_id']:
|
||||||
m['status'] = 'done'
|
m['status'] = 'done'
|
||||||
else:
|
else:
|
||||||
move_to_wanted = True
|
move_to_wanted = True
|
||||||
|
|
||||||
for t in m.profile.types:
|
profile = db.get('id', m['profile_id'])
|
||||||
for release in m.releases:
|
media_releases = db.get_many('release', m['_id'])
|
||||||
if t.quality.identifier is release.quality.identifier and (release.get('status') == 'done' and t.finish):
|
|
||||||
|
for q_identifier in profile['qualities']:
|
||||||
|
index = profile['qualities'].index(q_identifier)
|
||||||
|
|
||||||
|
for release in media_releases:
|
||||||
|
if q_identifier is release['quality'] and (release.get('status') == 'done' and profile['finish'][index]):
|
||||||
move_to_wanted = False
|
move_to_wanted = False
|
||||||
|
|
||||||
m['status'] = 'active' if move_to_wanted else 'done'
|
m['status'] = 'active' if move_to_wanted else 'done'
|
||||||
|
|
||||||
db.commit()
|
db.update(m)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
except:
|
except:
|
||||||
log.error('Failed restatus: %s', traceback.format_exc())
|
log.error('Failed restatus: %s', traceback.format_exc())
|
||||||
db.rollback()
|
|
||||||
finally:
|
|
||||||
pass #db.close()
|
|
||||||
|
|
||||||
@@ -117,12 +117,11 @@ class MovieBase(MovieTypeBase):
|
|||||||
added = True
|
added = True
|
||||||
do_search = False
|
do_search = False
|
||||||
search_after = search_after and self.conf('search_on_add', section = 'moviesearcher')
|
search_after = search_after and self.conf('search_on_add', section = 'moviesearcher')
|
||||||
|
onComplete = None
|
||||||
|
|
||||||
if new:
|
if new:
|
||||||
onComplete = None
|
|
||||||
if search_after:
|
if search_after:
|
||||||
onComplete = self.createOnComplete(m['_id'])
|
onComplete = self.createOnComplete(m['_id'])
|
||||||
|
|
||||||
fireEventAsync('movie.update_info', m['_id'], default_title = params.get('title', ''), on_complete = onComplete)
|
|
||||||
search_after = False
|
search_after = False
|
||||||
elif force_readd:
|
elif force_readd:
|
||||||
|
|
||||||
@@ -148,6 +147,9 @@ class MovieBase(MovieTypeBase):
|
|||||||
if added:
|
if added:
|
||||||
db.update(m)
|
db.update(m)
|
||||||
|
|
||||||
|
# Do full update to get images etc
|
||||||
|
fireEventAsync('movie.update_info', m['_id'], default_title = params.get('title'), on_complete = onComplete)
|
||||||
|
|
||||||
# Remove releases
|
# Remove releases
|
||||||
for rel in db.run('release', 'for_media', m['_id']):
|
for rel in db.run('release', 'for_media', m['_id']):
|
||||||
if rel['status'] is 'available':
|
if rel['status'] is 'available':
|
||||||
@@ -205,8 +207,9 @@ class MovieBase(MovieTypeBase):
|
|||||||
|
|
||||||
# Default title
|
# Default title
|
||||||
if kwargs.get('default_title'):
|
if kwargs.get('default_title'):
|
||||||
for title in m['titles']:
|
m['title'] = kwargs.get('default_title')
|
||||||
title.default = toUnicode(kwargs.get('default_title', '')).lower() == toUnicode(title.title).lower()
|
|
||||||
|
print m
|
||||||
|
|
||||||
db.update(m)
|
db.update(m)
|
||||||
|
|
||||||
@@ -266,35 +269,36 @@ class MovieBase(MovieTypeBase):
|
|||||||
|
|
||||||
titles = info.get('titles', [])
|
titles = info.get('titles', [])
|
||||||
log.debug('Adding titles: %s', titles)
|
log.debug('Adding titles: %s', titles)
|
||||||
counter = 0
|
|
||||||
|
|
||||||
|
# Define default title
|
||||||
def_title = None
|
def_title = None
|
||||||
for title in titles:
|
if default_title:
|
||||||
if (len(default_title) == 0 and counter == 0) or len(titles) == 1 or title.lower() == toUnicode(default_title.lower()) or (toUnicode(default_title) == six.u('') and toUnicode(titles[0]) == title):
|
counter = 0
|
||||||
def_title = toUnicode(title)
|
for title in titles:
|
||||||
break
|
if title.lower() == toUnicode(default_title.lower()) or (toUnicode(default_title) == six.u('') and toUnicode(titles[0]) == title):
|
||||||
counter += 1
|
def_title = toUnicode(title)
|
||||||
|
break
|
||||||
|
counter += 1
|
||||||
|
|
||||||
if not def_title:
|
if not def_title:
|
||||||
def_title = toUnicode(titles[0])
|
def_title = toUnicode(titles[0])
|
||||||
|
|
||||||
media = {
|
media['title'] = def_title
|
||||||
'title': def_title,
|
|
||||||
}
|
|
||||||
|
|
||||||
# Files
|
# Files
|
||||||
images = info.get('images', [])
|
images = info.get('images', [])
|
||||||
media['files'] = media.get('filed', [])
|
media['files'] = media.get('files', {})
|
||||||
for image_type in ['poster']:
|
for image_type in ['poster']:
|
||||||
for image in images.get(image_type, []):
|
for image in images.get(image_type, []):
|
||||||
if not isinstance(image, (str, unicode)):
|
if not isinstance(image, (str, unicode)):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
file_path = fireEvent('file.download', url = image, single = True)
|
file_type = 'image_%s' % image_type
|
||||||
media['files'].append({
|
if file_type not in media['files']:
|
||||||
'type': 'image_%s' % image_type,
|
file_path = fireEvent('file.download', url = image, single = True)
|
||||||
'path': file_path
|
media['files']['image_%s' % image_type] = [file_path];
|
||||||
})
|
|
||||||
|
break
|
||||||
|
|
||||||
db.update(media)
|
db.update(media)
|
||||||
|
|
||||||
@@ -306,7 +310,7 @@ class MovieBase(MovieTypeBase):
|
|||||||
|
|
||||||
def updateReleaseDate(self, media_id):
|
def updateReleaseDate(self, media_id):
|
||||||
"""
|
"""
|
||||||
Update releasedate (eta) info only
|
Update release_date (eta) info only
|
||||||
|
|
||||||
@param media_id: document id
|
@param media_id: document id
|
||||||
@return: dict, with dates dvd, theater, bluray, expires
|
@return: dict, with dates dvd, theater, bluray, expires
|
||||||
@@ -318,8 +322,8 @@ class MovieBase(MovieTypeBase):
|
|||||||
media = db.get('id', media_id)
|
media = db.get('id', media_id)
|
||||||
|
|
||||||
if not media.get('info'):
|
if not media.get('info'):
|
||||||
info_dict = self.updateInfo(media_id)
|
media = self.updateInfo(media_id)
|
||||||
dates = info_dict.get('info', {}).get('release_date')
|
dates = media.get('info', {}).get('release_date')
|
||||||
else:
|
else:
|
||||||
dates = media.get('info').get('release_date')
|
dates = media.get('info').get('release_date')
|
||||||
|
|
||||||
|
|||||||
@@ -59,9 +59,9 @@ var MovieList = new Class({
|
|||||||
movieDeleted: function(notification){
|
movieDeleted: function(notification){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
if(self.movies_added[notification.data.id]){
|
if(self.movies_added[notification.data._id]){
|
||||||
self.movies.each(function(movie){
|
self.movies.each(function(movie){
|
||||||
if(movie.get('id') == notification.data.id){
|
if(movie.get('_id') == notification.data._id){
|
||||||
movie.destroy();
|
movie.destroy();
|
||||||
delete self.movies_added[notification.data.id];
|
delete self.movies_added[notification.data.id];
|
||||||
self.setCounter(self.counter_count-1);
|
self.setCounter(self.counter_count-1);
|
||||||
@@ -288,7 +288,7 @@ var MovieList = new Class({
|
|||||||
'onSuccess': function(json){
|
'onSuccess': function(json){
|
||||||
available_chars = json.chars
|
available_chars = json.chars
|
||||||
|
|
||||||
json.chars.split('').each(function(c){
|
available_chars.each(function(c){
|
||||||
self.letters[c.capitalize()].addClass('available')
|
self.letters[c.capitalize()].addClass('available')
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -438,7 +438,7 @@ var MovieList = new Class({
|
|||||||
var ids = []
|
var ids = []
|
||||||
self.movies.each(function(movie){
|
self.movies.each(function(movie){
|
||||||
if (movie.isSelected())
|
if (movie.isSelected())
|
||||||
ids.include(movie.get('id'))
|
ids.include(movie.get('_id'))
|
||||||
});
|
});
|
||||||
|
|
||||||
return ids
|
return ids
|
||||||
@@ -467,7 +467,7 @@ var MovieList = new Class({
|
|||||||
|
|
||||||
self.offset = 0;
|
self.offset = 0;
|
||||||
if(self.scrollspy){
|
if(self.scrollspy){
|
||||||
self.load_more.show();
|
//self.load_more.show();
|
||||||
self.scrollspy.start();
|
self.scrollspy.start();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -427,7 +427,7 @@ MA.Release = new Class({
|
|||||||
|
|
||||||
Api.request('media.delete', {
|
Api.request('media.delete', {
|
||||||
'data': {
|
'data': {
|
||||||
'id': self.movie.get('id'),
|
'id': self.movie.get('_id'),
|
||||||
'delete_from': 'wanted'
|
'delete_from': 'wanted'
|
||||||
},
|
},
|
||||||
'onComplete': function(){
|
'onComplete': function(){
|
||||||
@@ -449,7 +449,7 @@ MA.Release = new Class({
|
|||||||
|
|
||||||
Api.request('movie.searcher.try_next', {
|
Api.request('movie.searcher.try_next', {
|
||||||
'data': {
|
'data': {
|
||||||
'id': self.movie.get('id')
|
'id': self.movie.get('_id')
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -604,13 +604,13 @@ MA.Edit = new Class({
|
|||||||
)
|
)
|
||||||
).inject(self.movie, 'top');
|
).inject(self.movie, 'top');
|
||||||
|
|
||||||
Array.each(self.movie.data.library.titles, function(alt){
|
Array.each(self.movie.data.info.titles, function(title){
|
||||||
new Element('option', {
|
new Element('option', {
|
||||||
'text': alt.title
|
'text': title
|
||||||
}).inject(self.title_select);
|
}).inject(self.title_select);
|
||||||
|
|
||||||
if(alt['default'])
|
if(title == self.movie.data.title)
|
||||||
self.title_select.set('value', alt.title);
|
self.title_select.set('value', title);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -643,7 +643,7 @@ MA.Edit = new Class({
|
|||||||
|
|
||||||
profiles.each(function(profile){
|
profiles.each(function(profile){
|
||||||
|
|
||||||
var profile_id = profile.id ? profile.id : profile.data.id;
|
var profile_id = profile.get('_id');
|
||||||
|
|
||||||
new Element('option', {
|
new Element('option', {
|
||||||
'value': profile_id,
|
'value': profile_id,
|
||||||
@@ -666,7 +666,7 @@ MA.Edit = new Class({
|
|||||||
|
|
||||||
Api.request('movie.edit', {
|
Api.request('movie.edit', {
|
||||||
'data': {
|
'data': {
|
||||||
'id': self.movie.get('id'),
|
'id': self.movie.get('_id'),
|
||||||
'default_title': self.title_select.get('value'),
|
'default_title': self.title_select.get('value'),
|
||||||
'profile_id': self.profile_select.get('value'),
|
'profile_id': self.profile_select.get('value'),
|
||||||
'category_id': self.category_select.get('value')
|
'category_id': self.category_select.get('value')
|
||||||
@@ -706,7 +706,7 @@ MA.Refresh = new Class({
|
|||||||
|
|
||||||
Api.request('media.refresh', {
|
Api.request('media.refresh', {
|
||||||
'data': {
|
'data': {
|
||||||
'id': self.movie.get('id')
|
'id': self.movie.get('_id')
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -817,7 +817,7 @@ MA.Delete = new Class({
|
|||||||
function(){
|
function(){
|
||||||
Api.request('media.delete', {
|
Api.request('media.delete', {
|
||||||
'data': {
|
'data': {
|
||||||
'id': self.movie.get('id'),
|
'id': self.movie.get('_id'),
|
||||||
'delete_from': self.movie.list.options.identifier
|
'delete_from': self.movie.list.options.identifier
|
||||||
},
|
},
|
||||||
'onComplete': function(){
|
'onComplete': function(){
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ var Movie = new Class({
|
|||||||
if(!self.data.releases)
|
if(!self.data.releases)
|
||||||
self.data.releases = [];
|
self.data.releases = [];
|
||||||
|
|
||||||
self.data.releases.push({'quality_id': data.quality_id, 'status': data.status});
|
self.data.releases.push({'quality_identifier': data.quality_identifier, 'status': data.status});
|
||||||
self.updateReleases();
|
self.updateReleases();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,7 +156,10 @@ var Movie = new Class({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
self.thumbnail = File.Select.single('poster', self.data.files || []),
|
self.thumbnail = (self.data.files && self.data.files.image_poster) ? new Element('img', {
|
||||||
|
'class': 'type_image poster',
|
||||||
|
'src': Api.createUrl('file.cache') + (self.data.files || {})['image_poster'][0]
|
||||||
|
}): null,
|
||||||
self.data_container = new Element('div.data.inlay.light').adopt(
|
self.data_container = new Element('div.data.inlay.light').adopt(
|
||||||
self.info_container = new Element('div.info').adopt(
|
self.info_container = new Element('div.info').adopt(
|
||||||
new Element('div.title').adopt(
|
new Element('div.title').adopt(
|
||||||
@@ -194,7 +197,7 @@ var Movie = new Class({
|
|||||||
if(self.profile.data)
|
if(self.profile.data)
|
||||||
self.profile.getTypes().each(function(type){
|
self.profile.getTypes().each(function(type){
|
||||||
|
|
||||||
var q = self.addQuality(type.quality_id || type.get('quality_id'));
|
var q = self.addQuality(type.quality_identifier || type.get('quality_identifier'));
|
||||||
if((type.finish == true || type.get('finish')) && !q.hasClass('finish')){
|
if((type.finish == true || type.get('finish')) && !q.hasClass('finish')){
|
||||||
q.addClass('finish');
|
q.addClass('finish');
|
||||||
q.set('title', q.get('title') + ' Will finish searching for this movie if this quality is found.')
|
q.set('title', q.get('title') + ' Will finish searching for this movie if this quality is found.')
|
||||||
@@ -223,7 +226,7 @@ var Movie = new Class({
|
|||||||
status = release.status;
|
status = release.status;
|
||||||
|
|
||||||
if(!q && (status == 'snatched' || status == 'seeding' || status == 'done'))
|
if(!q && (status == 'snatched' || status == 'seeding' || status == 'done'))
|
||||||
var q = self.addQuality(release.quality_id)
|
var q = self.addQuality(release.quality_identifier)
|
||||||
|
|
||||||
if (q && !q.hasClass(status)){
|
if (q && !q.hasClass(status)){
|
||||||
q.addClass(status);
|
q.addClass(status);
|
||||||
@@ -233,10 +236,10 @@ var Movie = new Class({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
addQuality: function(quality_id){
|
addQuality: function(quality_identifier){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var q = Quality.getQuality(quality_id);
|
var q = Quality.getQuality(quality_identifier);
|
||||||
return new Element('span', {
|
return new Element('span', {
|
||||||
'text': q.label,
|
'text': q.label,
|
||||||
'class': 'q_'+q.identifier + ' q_id' + q.id,
|
'class': 'q_'+q.identifier + ' q_id' + q.id,
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
|
|||||||
return
|
return
|
||||||
|
|
||||||
pre_releases = fireEvent('quality.pre_releases', single = True)
|
pre_releases = fireEvent('quality.pre_releases', single = True)
|
||||||
release_dates = fireEvent('movie.update_release_date', media_id = movie['_id'], merge = True)
|
release_dates = fireEvent('movie.update_release_dates', movie['_id'], merge = True)
|
||||||
|
|
||||||
found_releases = []
|
found_releases = []
|
||||||
too_early_to_search = []
|
too_early_to_search = []
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ var NotificationBase = new Class({
|
|||||||
// Process data
|
// Process data
|
||||||
if(json){
|
if(json){
|
||||||
Array.each(json.result, function(result){
|
Array.each(json.result, function(result){
|
||||||
App.trigger(result.type, [result]);
|
App.trigger(result._t, [result]);
|
||||||
if(result.message && result.read === undefined)
|
if(result.message && result.read === undefined)
|
||||||
self.showMessage(result.message);
|
self.showMessage(result.message);
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
from couchpotato import get_session
|
from couchpotato import get_db
|
||||||
from couchpotato.api import addApiView
|
from couchpotato.api import addApiView
|
||||||
from couchpotato.core.event import fireEvent
|
from couchpotato.core.event import fireEvent
|
||||||
from couchpotato.core.helpers.variable import splitString, tryInt
|
from couchpotato.core.helpers.variable import splitString, tryInt
|
||||||
from couchpotato.core.logger import CPLog
|
from couchpotato.core.logger import CPLog
|
||||||
from couchpotato.core.plugins.base import Plugin
|
from couchpotato.core.plugins.base import Plugin
|
||||||
from couchpotato.core.settings.model import Media, Library, LibraryTitle, \
|
|
||||||
Release
|
|
||||||
from sqlalchemy.orm import joinedload_all
|
|
||||||
from sqlalchemy.sql.expression import asc, or_
|
|
||||||
import random as rndm
|
import random as rndm
|
||||||
import time
|
import time
|
||||||
|
|
||||||
@@ -21,26 +17,21 @@ class Dashboard(Plugin):
|
|||||||
|
|
||||||
def getSoonView(self, limit_offset = None, random = False, late = False, **kwargs):
|
def getSoonView(self, limit_offset = None, random = False, late = False, **kwargs):
|
||||||
|
|
||||||
db = get_session()
|
db = get_db()
|
||||||
now = time.time()
|
now = time.time()
|
||||||
|
|
||||||
# Get profiles first, determine pre or post theater
|
# Get profiles first, determine pre or post theater
|
||||||
profiles = fireEvent('profile.all', single = True)
|
profiles = fireEvent('profile.all', single = True)
|
||||||
qualities = fireEvent('quality.all', single = True)
|
|
||||||
pre_releases = fireEvent('quality.pre_releases', single = True)
|
pre_releases = fireEvent('quality.pre_releases', single = True)
|
||||||
|
|
||||||
id_pre = {}
|
|
||||||
for quality in qualities:
|
|
||||||
id_pre[quality.get('id')] = quality.get('identifier') in pre_releases
|
|
||||||
|
|
||||||
# See what the profile contain and cache it
|
# See what the profile contain and cache it
|
||||||
profile_pre = {}
|
profile_pre = {}
|
||||||
for profile in profiles:
|
for profile in profiles:
|
||||||
contains = {}
|
contains = {}
|
||||||
for profile_type in profile.get('types', []):
|
for q_identifier in profile.get('qualities', []):
|
||||||
contains['theater' if id_pre.get(profile_type.get('quality_id')) else 'dvd'] = True
|
contains['theater' if q_identifier in pre_releases else 'dvd'] = True
|
||||||
|
|
||||||
profile_pre[profile.get('id')] = contains
|
profile_pre[profile.get('_id')] = contains
|
||||||
|
|
||||||
# Add limit
|
# Add limit
|
||||||
limit = 12
|
limit = 12
|
||||||
@@ -48,43 +39,32 @@ class Dashboard(Plugin):
|
|||||||
splt = splitString(limit_offset) if isinstance(limit_offset, (str, unicode)) else limit_offset
|
splt = splitString(limit_offset) if isinstance(limit_offset, (str, unicode)) else limit_offset
|
||||||
limit = tryInt(splt[0])
|
limit = tryInt(splt[0])
|
||||||
|
|
||||||
# Get all active movies
|
# Get all active medias
|
||||||
q = db.query(Media) \
|
active_ids = [x['_id'] for x in db.get_many('media_status', 'active')]
|
||||||
.join(Library) \
|
|
||||||
.outerjoin(Media.releases) \
|
|
||||||
.filter(Media.status_id == active_status.get('id')) \
|
|
||||||
.with_entities(Media.id, Media.profile_id, Library.info, Library.year) \
|
|
||||||
.group_by(Media.id) \
|
|
||||||
.filter(or_(Release.id == None, Release.status_id == ignored_status.get('id')))
|
|
||||||
|
|
||||||
if not random:
|
medias = []
|
||||||
q = q.join(LibraryTitle) \
|
if len(active_ids) > 0:
|
||||||
.filter(LibraryTitle.default == True) \
|
|
||||||
.order_by(asc(LibraryTitle.simple_title))
|
|
||||||
|
|
||||||
active = q.all()
|
# Order by title or randomize
|
||||||
movies = []
|
if not random:
|
||||||
|
orders_ids = db.all('media_title')
|
||||||
|
active_ids = [x['_id'] for x in orders_ids if x['_id'] in active_ids]
|
||||||
|
else:
|
||||||
|
rndm.shuffle(active_ids)
|
||||||
|
|
||||||
if len(active) > 0:
|
for media_id in active_ids:
|
||||||
|
media = db.get('id', media_id)
|
||||||
|
|
||||||
# Do the shuffle
|
pp = profile_pre.get(media['profile_id'])
|
||||||
if random:
|
|
||||||
rndm.shuffle(active)
|
|
||||||
|
|
||||||
movie_ids = []
|
|
||||||
for movie in active:
|
|
||||||
movie_id, profile_id, info, year = movie
|
|
||||||
|
|
||||||
pp = profile_pre.get(profile_id)
|
|
||||||
if not pp: continue
|
if not pp: continue
|
||||||
|
|
||||||
eta = info.get('release_date', {}) or {}
|
eta = media['info'].get('release_date', {}) or {}
|
||||||
coming_soon = False
|
coming_soon = False
|
||||||
|
|
||||||
# Theater quality
|
# Theater quality
|
||||||
if pp.get('theater') and fireEvent('movie.searcher.could_be_released', True, eta, year, single = True):
|
if pp.get('theater') and fireEvent('movie.searcher.could_be_released', True, eta, media['info']['year'], single = True):
|
||||||
coming_soon = True
|
coming_soon = True
|
||||||
elif pp.get('dvd') and fireEvent('movie.searcher.could_be_released', False, eta, year, single = True):
|
elif pp.get('dvd') and fireEvent('movie.searcher.could_be_released', False, eta, media['info']['year'], single = True):
|
||||||
coming_soon = True
|
coming_soon = True
|
||||||
|
|
||||||
if coming_soon:
|
if coming_soon:
|
||||||
@@ -92,37 +72,15 @@ class Dashboard(Plugin):
|
|||||||
# Don't list older movies
|
# Don't list older movies
|
||||||
if ((not late and (not eta.get('dvd') and not eta.get('theater') or eta.get('dvd') and eta.get('dvd') > (now - 2419200))) or
|
if ((not late and (not eta.get('dvd') and not eta.get('theater') or eta.get('dvd') and eta.get('dvd') > (now - 2419200))) or
|
||||||
(late and (eta.get('dvd', 0) > 0 or eta.get('theater')) and eta.get('dvd') < (now - 2419200))):
|
(late and (eta.get('dvd', 0) > 0 or eta.get('theater')) and eta.get('dvd') < (now - 2419200))):
|
||||||
movie_ids.append(movie_id)
|
medias.append(media)
|
||||||
|
|
||||||
if len(movie_ids) >= limit:
|
if len(medias) >= limit:
|
||||||
break
|
break
|
||||||
|
|
||||||
if len(movie_ids) > 0:
|
|
||||||
|
|
||||||
# Get all movie information
|
|
||||||
movies_raw = db.query(Media) \
|
|
||||||
.options(joinedload_all('library.titles')) \
|
|
||||||
.options(joinedload_all('library.files')) \
|
|
||||||
.options(joinedload_all('files')) \
|
|
||||||
.filter(Media.id.in_(movie_ids)) \
|
|
||||||
.all()
|
|
||||||
|
|
||||||
# Create dict by movie id
|
|
||||||
movie_dict = {}
|
|
||||||
for movie in movies_raw:
|
|
||||||
movie_dict[movie.id] = movie
|
|
||||||
|
|
||||||
for movie_id in movie_ids:
|
|
||||||
movies.append(movie_dict[movie_id].to_dict({
|
|
||||||
'library': {'titles': {}, 'files': {}},
|
|
||||||
'files': {},
|
|
||||||
}))
|
|
||||||
|
|
||||||
pass #db.close()
|
|
||||||
return {
|
return {
|
||||||
'success': True,
|
'success': True,
|
||||||
'empty': len(movies) == 0,
|
'empty': len(medias) == 0,
|
||||||
'movies': movies,
|
'movies': medias,
|
||||||
}
|
}
|
||||||
|
|
||||||
getLateView = getSoonView
|
getLateView = getSoonView
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
var File = new Class({
|
|
||||||
|
|
||||||
initialize: function(type, file){
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
if(!file){
|
|
||||||
self.empty = true;
|
|
||||||
self.el = new Element('div.empty_file.'+type);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
self.data = file;
|
|
||||||
self.type = File.Type.get(file.type_id);
|
|
||||||
|
|
||||||
self['create'+(self.type.type).capitalize()]()
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
createImage: function(){
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
var file_name = self.data.path.replace(/^.*[\\\/]/, '');
|
|
||||||
|
|
||||||
self.el = new Element('div', {
|
|
||||||
'class': 'type_image ' + self.type.identifier,
|
|
||||||
'styles': {
|
|
||||||
'background-image': 'url('+Api.createUrl('file.cache') + file_name+')'
|
|
||||||
}
|
|
||||||
}).adopt(
|
|
||||||
new Element('img', {
|
|
||||||
'src': Api.createUrl('file.cache') + file_name
|
|
||||||
})
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|
|
||||||
toElement: function(){
|
|
||||||
return this.el;
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
var FileSelect = new Class({
|
|
||||||
|
|
||||||
multiple: function(type, files, single){
|
|
||||||
|
|
||||||
var results = files.filter(function(file){
|
|
||||||
return file.type_id == File.Type.get(type).id;
|
|
||||||
});
|
|
||||||
|
|
||||||
if(single)
|
|
||||||
return new File(type, results.pop());
|
|
||||||
|
|
||||||
return results;
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
single: function(type, files){
|
|
||||||
return this.multiple(type, files, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
window.File.Select = new FileSelect();
|
|
||||||
|
|
||||||
var FileTypeBase = new Class({
|
|
||||||
|
|
||||||
setup: function(types){
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
self.typesById = {};
|
|
||||||
self.typesByKey = {};
|
|
||||||
Object.each(types, function(type){
|
|
||||||
self.typesByKey[type.identifier] = type;
|
|
||||||
self.typesById[type.id] = type;
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
get: function(identifier){
|
|
||||||
if(typeOf(identifier) == 'number')
|
|
||||||
return this.typesById[identifier]
|
|
||||||
else
|
|
||||||
return this.typesByKey[identifier]
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
window.File.Type = new FileTypeBase();
|
|
||||||
@@ -124,7 +124,7 @@ class Manage(Plugin):
|
|||||||
fireEvent('media.delete', media_id = done_movie['id'], delete_from = 'all')
|
fireEvent('media.delete', media_id = done_movie['id'], delete_from = 'all')
|
||||||
else:
|
else:
|
||||||
|
|
||||||
releases = fireEvent('release.for_movie', id = done_movie.get('id'), single = True)
|
releases = fireEvent('release.for_movie', id = done_movie.get('_id'), single = True)
|
||||||
|
|
||||||
for release in releases:
|
for release in releases:
|
||||||
if len(release.get('files', [])) > 0:
|
if len(release.get('files', [])) > 0:
|
||||||
|
|||||||
@@ -56,8 +56,7 @@ class ProfilePlugin(Plugin):
|
|||||||
|
|
||||||
for media in medias:
|
for media in medias:
|
||||||
if media.get('profile_id') not in profile_ids:
|
if media.get('profile_id') not in profile_ids:
|
||||||
default_profile = self.default()
|
media['profile_id'] = profile_ids[0].get('_id')
|
||||||
media['profile_id'] = default_profile.get('id')
|
|
||||||
db.update(media)
|
db.update(media)
|
||||||
except:
|
except:
|
||||||
log.error('Failed: %s', traceback.format_exc())
|
log.error('Failed: %s', traceback.format_exc())
|
||||||
|
|||||||
@@ -54,10 +54,20 @@ var Profile = new Class({
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
self.makeSortable()
|
self.makeSortable();
|
||||||
|
|
||||||
|
// Combine qualities and properties into types
|
||||||
|
data.types = [];
|
||||||
|
data.qualities.each(function(quality, nr){
|
||||||
|
data.types.include({
|
||||||
|
'quality_identifier': quality,
|
||||||
|
'finish': data.finish[nr] || false,
|
||||||
|
'wait_for': data.wait_for[nr] || 0
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
if(data.types)
|
if(data.types)
|
||||||
Object.each(data.types, self.addType.bind(self))
|
data.types.each(self.addType.bind(self));
|
||||||
else
|
else
|
||||||
self.delete_button.hide();
|
self.delete_button.hide();
|
||||||
|
|
||||||
@@ -111,8 +121,9 @@ var Profile = new Class({
|
|||||||
Array.each(self.type_container.getElements('.type'), function(type){
|
Array.each(self.type_container.getElements('.type'), function(type){
|
||||||
if(!type.hasClass('deleted') && type.getElement('select').get('value') > 0)
|
if(!type.hasClass('deleted') && type.getElement('select').get('value') > 0)
|
||||||
data.types.include({
|
data.types.include({
|
||||||
'quality_id': type.getElement('select').get('value'),
|
'quality_identifier': type.getElement('select').get('value'),
|
||||||
'finish': +type.getElement('input[type=checkbox]').checked
|
'finish': +type.getElement('input[type=checkbox]').checked,
|
||||||
|
'wait_for': 0
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -145,7 +156,7 @@ var Profile = new Class({
|
|||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
return self.types.filter(function(type){
|
return self.types.filter(function(type){
|
||||||
return type.get('quality_id')
|
return type.get('quality_identifier')
|
||||||
});
|
});
|
||||||
|
|
||||||
},
|
},
|
||||||
@@ -264,7 +275,7 @@ Profile.Type = new Class({
|
|||||||
new Element('span.handle')
|
new Element('span.handle')
|
||||||
);
|
);
|
||||||
|
|
||||||
self.el[self.data.quality_id > 0 ? 'removeClass' : 'addClass']('is_empty');
|
self.el[self.data.quality_identifier ? 'removeClass' : 'addClass']('is_empty');
|
||||||
|
|
||||||
self.finish_class = new Form.Check(self.finish);
|
self.finish_class = new Form.Check(self.finish);
|
||||||
|
|
||||||
@@ -287,11 +298,11 @@ Profile.Type = new Class({
|
|||||||
Object.each(Quality.qualities, function(q){
|
Object.each(Quality.qualities, function(q){
|
||||||
new Element('option', {
|
new Element('option', {
|
||||||
'text': q.label,
|
'text': q.label,
|
||||||
'value': q.id
|
'value': q.identifier
|
||||||
}).inject(self.qualities)
|
}).inject(self.qualities)
|
||||||
});
|
});
|
||||||
|
|
||||||
self.qualities.set('value', self.data.quality_id);
|
self.qualities.set('value', self.data.quality_identifier);
|
||||||
|
|
||||||
return self.qualities;
|
return self.qualities;
|
||||||
|
|
||||||
@@ -301,8 +312,9 @@ Profile.Type = new Class({
|
|||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'quality_id': self.qualities.get('value'),
|
'quality_identifier': self.qualities.get('value'),
|
||||||
'finish': +self.finish.checked
|
'finish': +self.finish.checked,
|
||||||
|
'wait_for': 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ var QualityBase = new Class({
|
|||||||
|
|
||||||
getProfile: function(id){
|
getProfile: function(id){
|
||||||
return this.profiles.filter(function(profile){
|
return this.profiles.filter(function(profile){
|
||||||
return profile.data.id == id
|
return profile.data._id == id
|
||||||
}).pick()
|
}).pick()
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -28,9 +28,9 @@ var QualityBase = new Class({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getQuality: function(id){
|
getQuality: function(identifier){
|
||||||
return this.qualities.filter(function(q){
|
return this.qualities.filter(function(q){
|
||||||
return q.id == id;
|
return q.identifier == identifier;
|
||||||
}).pick();
|
}).pick();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -19,13 +19,13 @@ class ReleaseIndex(TreeBasedIndex):
|
|||||||
for release in db.get_many('release', media_id, with_doc = True):
|
for release in db.get_many('release', media_id, with_doc = True):
|
||||||
yield release['doc']
|
yield release['doc']
|
||||||
|
|
||||||
def run_with_status(self, db, status = []):
|
def run_with_status(self, db, status = [], with_doc = True):
|
||||||
|
|
||||||
status = list(status if isinstance(status, (list, tuple)) else [status])
|
status = list(status if isinstance(status, (list, tuple)) else [status])
|
||||||
|
|
||||||
for s in status:
|
for s in status:
|
||||||
for ms in db.get_many('release_status', s, with_doc = True):
|
for ms in db.get_many('release_status', s, with_doc = with_doc):
|
||||||
yield ms['doc']
|
yield ms['doc'] if with_doc else ms
|
||||||
|
|
||||||
|
|
||||||
class ReleaseStatusIndex(TreeBasedIndex):
|
class ReleaseStatusIndex(TreeBasedIndex):
|
||||||
@@ -39,7 +39,7 @@ class ReleaseStatusIndex(TreeBasedIndex):
|
|||||||
|
|
||||||
def make_key_value(self, data):
|
def make_key_value(self, data):
|
||||||
if data.get('_t') == 'release' and data.get('status'):
|
if data.get('_t') == 'release' and data.get('status'):
|
||||||
return md5(data.get('status')).hexdigest(), None
|
return md5(data.get('status')).hexdigest(), {'media_id': data.get('media_id')}
|
||||||
|
|
||||||
|
|
||||||
class ReleaseIDIndex(TreeBasedIndex):
|
class ReleaseIDIndex(TreeBasedIndex):
|
||||||
@@ -53,4 +53,4 @@ class ReleaseIDIndex(TreeBasedIndex):
|
|||||||
|
|
||||||
def make_key_value(self, data):
|
def make_key_value(self, data):
|
||||||
if data.get('_t') == 'release' and data.get('identifier'):
|
if data.get('_t') == 'release' and data.get('identifier'):
|
||||||
return md5(data.get('identifier')).hexdigest(), None
|
return md5(data.get('identifier')).hexdigest(), {'media_id': data.get('media_id')}
|
||||||
@@ -461,7 +461,7 @@ class Renamer(Plugin):
|
|||||||
self.tagRelease(group = group, tag = 'exists')
|
self.tagRelease(group = group, tag = 'exists')
|
||||||
|
|
||||||
# Notify on rename fail
|
# Notify on rename fail
|
||||||
download_message = 'Renaming of %s (%s) cancelled, exists in %s already.' % (movie.library.titles[0].title, group['meta_data']['quality']['label'], release.quality.label)
|
download_message = 'Renaming of %s (%s) cancelled, exists in %s already.' % (getTitle(movie), group['meta_data']['quality']['label'], release.quality.label)
|
||||||
fireEvent('movie.renaming.canceled', message = download_message, data = group)
|
fireEvent('movie.renaming.canceled', message = download_message, data = group)
|
||||||
remove_leftovers = False
|
remove_leftovers = False
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user