Try NoSQL
This commit is contained in:
1 parent
aab10fb599
commit
a254886bad
65 files changed
+7372
-761
No files matched your search
@@ -42,11 +42,11 @@ class Core(Plugin):
|
||||
|
||||
addEvent('app.shutdown', self.shutdown)
|
||||
addEvent('app.restart', self.restart)
|
||||
addEvent('app.load', self.launchBrowser, priority = 1)
|
||||
addEvent('app.load2', self.launchBrowser, priority = 1)
|
||||
addEvent('app.base_url', self.createBaseUrl)
|
||||
addEvent('app.api_url', self.createApiUrl)
|
||||
addEvent('app.version', self.version)
|
||||
addEvent('app.load', self.checkDataDir)
|
||||
addEvent('app.load2', self.checkDataDir)
|
||||
|
||||
addEvent('setting.save.core.password', self.md5Password)
|
||||
addEvent('setting.save.core.api_key', self.checkApikey)
|
||||
|
||||
@@ -74,7 +74,7 @@ class ClientScript(Plugin):
|
||||
addEvent('clientscript.get_scripts', self.getScripts)
|
||||
|
||||
if not Env.get('dev'):
|
||||
addEvent('app.load', self.minify)
|
||||
addEvent('app.load2', self.minify)
|
||||
|
||||
self.addCore()
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ if Env.get('desktop'):
|
||||
|
||||
# Events to desktop
|
||||
addEvent('app.after_shutdown', desktop.afterShutdown)
|
||||
addEvent('app.load', desktop.onAppLoad, priority = 110)
|
||||
addEvent('app.load2', desktop.onAppLoad, priority = 110)
|
||||
|
||||
def onClose(self, event):
|
||||
return fireEvent('app.shutdown', single = True)
|
||||
|
||||
@@ -33,8 +33,8 @@ class Updater(Plugin):
|
||||
else:
|
||||
self.updater = SourceUpdater()
|
||||
|
||||
addEvent('app.load', self.logVersion, priority = 10000)
|
||||
addEvent('app.load', self.setCrons)
|
||||
addEvent('app.load2', self.logVersion, priority = 10000)
|
||||
addEvent('app.load2', self.setCrons)
|
||||
addEvent('updater.info', self.info)
|
||||
|
||||
addApiView('updater.info', self.info, docs = {
|
||||
|
||||
@@ -23,7 +23,7 @@ class rTorrent(Downloader):
|
||||
def __init__(self):
|
||||
super(rTorrent, self).__init__()
|
||||
|
||||
addEvent('app.load', self.migrate)
|
||||
addEvent('app.load2', self.migrate)
|
||||
|
||||
def migrate(self):
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import traceback
|
||||
from couchpotato import get_session
|
||||
from couchpotato import get_session, get_db, CPLog
|
||||
from couchpotato.core.event import addEvent, fireEventAsync, fireEvent
|
||||
from couchpotato.core.plugins.base import Plugin
|
||||
from couchpotato.core.settings.model import Media
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class MediaBase(Plugin):
|
||||
|
||||
@@ -24,20 +26,19 @@ class MediaBase(Plugin):
|
||||
def getType(self):
|
||||
return self._type
|
||||
|
||||
def createOnComplete(self, id):
|
||||
def createOnComplete(self, media_id):
|
||||
|
||||
def onComplete():
|
||||
try:
|
||||
db = get_session()
|
||||
media = db.query(Media).filter_by(id = id).first()
|
||||
media_dict = media.to_dict(self.default_dict)
|
||||
event_name = '%s.searcher.single' % media.type
|
||||
db = get_db()
|
||||
media = db.get('id', media_id)
|
||||
event_name = '%s.searcher.single' % media.get('type')
|
||||
|
||||
fireEvent(event_name, media_dict, on_complete = self.createNotifyFront(id))
|
||||
fireEvent(event_name, media, on_complete = self.createNotifyFront(media_id))
|
||||
except:
|
||||
log.error('Failed creating onComplete: %s', traceback.format_exc())
|
||||
finally:
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
return onComplete
|
||||
|
||||
@@ -45,15 +46,14 @@ class MediaBase(Plugin):
|
||||
|
||||
def notifyFront():
|
||||
try:
|
||||
db = get_session()
|
||||
media = db.query(Media).filter_by(id = media_id).first()
|
||||
media_dict = media.to_dict(self.default_dict)
|
||||
event_name = '%s.update' % media.type
|
||||
db = get_db()
|
||||
media = db.get('id', media_id)
|
||||
event_name = '%s.update' % media.get('type')
|
||||
|
||||
fireEvent('notify.frontend', type = event_name, data = media_dict)
|
||||
fireEvent('notify.frontend', type = event_name, data = media)
|
||||
except:
|
||||
log.error('Failed creating onComplete: %s', traceback.format_exc())
|
||||
finally:
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
return notifyFront
|
||||
@@ -0,0 +1,60 @@
|
||||
from CodernityDB.hash_index import HashIndex
|
||||
from CodernityDB.tree_index import MultiTreeBasedIndex
|
||||
|
||||
|
||||
class MediaIMDBIndex(HashIndex):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['key_format'] = 'I'
|
||||
super(MediaIMDBIndex, self).__init__(*args, **kwargs)
|
||||
|
||||
def make_key(self, key):
|
||||
return int(key.strip('t'))
|
||||
|
||||
def make_key_value(self, data):
|
||||
if data.get('type') == 'media' and data.get('identifier'):
|
||||
return int(data['identifier'].strip('t')), None
|
||||
|
||||
|
||||
class MediaStatusIndex(HashIndex):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['key_format'] = 's'
|
||||
super(MediaStatusIndex, self).__init__(*args, **kwargs)
|
||||
|
||||
def make_key(self, key):
|
||||
return int(key.strip('t'))
|
||||
|
||||
def make_key_value(self, data):
|
||||
if data.get('type') == 'media' and data.get('identifier'):
|
||||
return int(data['identifier'].strip('t')), None
|
||||
|
||||
|
||||
class TitleIndex(MultiTreeBasedIndex):
|
||||
|
||||
custom_header = """from CodernityDB.tree_index import MultiTreeBasedIndex
|
||||
from itertools import izip"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['key_format'] = '32s'
|
||||
super(TitleIndex, self).__init__(*args, **kwargs)
|
||||
self.__l = kwargs.get('w_len', 2)
|
||||
|
||||
def make_key_value(self, data):
|
||||
|
||||
if data.get('type') == 'title' and len(data.get('title', '')) > 0:
|
||||
|
||||
out = set()
|
||||
title = data.get('title').lower()
|
||||
l = self.__l
|
||||
max_l = len(title)
|
||||
for x in xrange(l - 1, max_l):
|
||||
m = (title, )
|
||||
for y in xrange(0, x):
|
||||
m += (title[y + 1:],)
|
||||
out.update(set(''.join(x).rjust(32, '_').lower() for x in izip(*m))) #ignore import error
|
||||
|
||||
return out, {'media_id': data.get('media_id')}
|
||||
|
||||
def make_key(self, key):
|
||||
return key.rjust(32, '_').lower()
|
||||
@@ -1,11 +1,12 @@
|
||||
import traceback
|
||||
from couchpotato import get_session, tryInt
|
||||
from couchpotato import get_session, tryInt, get_db
|
||||
from couchpotato.api import addApiView
|
||||
from couchpotato.core.event import fireEvent, fireEventAsync, addEvent
|
||||
from couchpotato.core.helpers.encoding import toUnicode
|
||||
from couchpotato.core.helpers.variable import mergeDicts, splitString, getImdb, getTitle
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.media import MediaBase
|
||||
from .index import MediaIMDBIndex, TitleIndex, MediaStatusIndex
|
||||
from couchpotato.core.settings.model import Library, LibraryTitle, Release, \
|
||||
Media
|
||||
from sqlalchemy.orm import joinedload_all
|
||||
@@ -60,16 +61,40 @@ class MediaPlugin(MediaBase):
|
||||
|
||||
addApiView('media.available_chars', self.charView)
|
||||
|
||||
addEvent('app.load', self.addSingleRefreshView)
|
||||
addEvent('app.load', self.addSingleListView)
|
||||
addEvent('app.load', self.addSingleCharView)
|
||||
addEvent('app.load', self.addSingleDeleteView)
|
||||
addEvent('database.setup', self.databaseSetup)
|
||||
|
||||
addEvent('app.load2', self.addSingleRefreshView)
|
||||
addEvent('app.load2', self.addSingleListView)
|
||||
addEvent('app.load2', self.addSingleCharView)
|
||||
addEvent('app.load2', self.addSingleDeleteView)
|
||||
|
||||
addEvent('media.get', self.get)
|
||||
addEvent('media.list', self.list)
|
||||
addEvent('media.delete', self.delete)
|
||||
addEvent('media.restatus', self.restatus)
|
||||
|
||||
def databaseSetup(self):
|
||||
|
||||
db = get_db()
|
||||
|
||||
try:
|
||||
db.add_index(MediaIMDBIndex(db.path, 'media'))
|
||||
except:
|
||||
log.debug('Index already exists')
|
||||
db.update_index(MediaIMDBIndex(db.path, 'media'))
|
||||
|
||||
try:
|
||||
db.add_index(TitleIndex(db.path, 'media_title'))
|
||||
except:
|
||||
log.debug('Index already exists')
|
||||
db.update_index(TitleIndex(db.path, 'media_title'))
|
||||
|
||||
try:
|
||||
db.add_index(MediaStatusIndex(db.path, 'media_status'))
|
||||
except:
|
||||
log.debug('Index already exists')
|
||||
db.update_index(MediaStatusIndex(db.path, 'media_status'))
|
||||
|
||||
def refresh(self, id = '', **kwargs):
|
||||
handlers = []
|
||||
ids = splitString(id)
|
||||
@@ -87,24 +112,23 @@ class MediaPlugin(MediaBase):
|
||||
'success': True,
|
||||
}
|
||||
|
||||
def createRefreshHandler(self, id):
|
||||
db = get_session()
|
||||
def createRefreshHandler(self, media_id):
|
||||
|
||||
media = db.query(Media).filter_by(id = id).first()
|
||||
try:
|
||||
media = get_db().get('id', media_id)
|
||||
|
||||
if media:
|
||||
|
||||
default_title = getTitle(media.library)
|
||||
identifier = media.library.identifier
|
||||
event = 'library.update.%s' % media.type
|
||||
default_title = getTitle(media_id)
|
||||
event = 'library.update.%s' % media.get('type')
|
||||
|
||||
def handler():
|
||||
fireEvent(event, identifier = identifier, default_title = default_title, on_complete = self.createOnComplete(id))
|
||||
fireEvent(event, identifier = media.get('identifier'), default_title = default_title, on_complete = self.createOnComplete(media_id))
|
||||
|
||||
db.close()
|
||||
if handler:
|
||||
return handler
|
||||
|
||||
except:
|
||||
log.error('Refresh handler for non existing media: %s', traceback.format_exc())
|
||||
|
||||
if handler:
|
||||
return handler
|
||||
|
||||
def addSingleRefreshView(self):
|
||||
|
||||
@@ -113,20 +137,19 @@ class MediaPlugin(MediaBase):
|
||||
|
||||
def get(self, media_id):
|
||||
|
||||
db = get_session()
|
||||
db = get_db()
|
||||
|
||||
imdb_id = getImdb(str(media_id))
|
||||
|
||||
if imdb_id:
|
||||
m = db.query(Media).filter(Media.library.has(identifier = imdb_id)).first()
|
||||
m = db.get('media', imdb_id, with_doc = True)['doc']
|
||||
else:
|
||||
m = db.query(Media).filter_by(id = media_id).first()
|
||||
m = db.get('id', media_id)
|
||||
|
||||
results = None
|
||||
if m:
|
||||
results = m.to_dict(self.default_dict)
|
||||
results = db.run('media', 'to_dict', m, self.default_dict)
|
||||
|
||||
db.close()
|
||||
return results
|
||||
|
||||
def getView(self, id = None, **kwargs):
|
||||
@@ -262,7 +285,7 @@ class MediaPlugin(MediaBase):
|
||||
'releases_count': releases_count.get(media_id),
|
||||
}))
|
||||
|
||||
db.close()
|
||||
pass #db.close()
|
||||
return total_count, movies
|
||||
|
||||
def listView(self, **kwargs):
|
||||
@@ -356,7 +379,7 @@ class MediaPlugin(MediaBase):
|
||||
if len(chars) == 25:
|
||||
break
|
||||
|
||||
db.close()
|
||||
pass #db.close()
|
||||
return ''.join(sorted(chars))
|
||||
|
||||
def charView(self, **kwargs):
|
||||
@@ -428,7 +451,7 @@ class MediaPlugin(MediaBase):
|
||||
log.error('Failed deleting media: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
return True
|
||||
|
||||
@@ -481,5 +504,5 @@ class MediaPlugin(MediaBase):
|
||||
log.error('Failed restatus: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
@@ -25,7 +25,7 @@ class Search(Plugin):
|
||||
}"""}
|
||||
})
|
||||
|
||||
addEvent('app.load', self.addSingleSearches)
|
||||
addEvent('app.load2', self.addSingleSearches)
|
||||
|
||||
def search(self, q = '', types = None, **kwargs):
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ class SearcherBase(Plugin):
|
||||
fireEvent('schedule.cron', '%s.searcher.all' % _type, self.searchAll,
|
||||
day = self.conf('cron_day'), hour = self.conf('cron_hour'), minute = self.conf('cron_minute'))
|
||||
|
||||
addEvent('app.load', setCrons)
|
||||
addEvent('app.load2', setCrons)
|
||||
addEvent('setting.save.%s_searcher.cron_day.after' % _type, setCrons)
|
||||
addEvent('setting.save.%s_searcher.cron_hour.after' % _type, setCrons)
|
||||
addEvent('setting.save.%s_searcher.cron_minute.after' % _type, setCrons)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import traceback
|
||||
from couchpotato import get_session
|
||||
from couchpotato import get_session, get_db
|
||||
from couchpotato.api import addApiView
|
||||
from couchpotato.core.event import fireEvent, fireEventAsync, addEvent
|
||||
from couchpotato.core.helpers.encoding import toUnicode
|
||||
@@ -62,78 +62,78 @@ class MovieBase(MovieTypeBase):
|
||||
except:
|
||||
pass
|
||||
|
||||
library = fireEvent('library.add.movie', single = True, attrs = params, update_after = update_library)
|
||||
|
||||
# Status
|
||||
status_active, snatched_status, ignored_status, done_status, downloaded_status = \
|
||||
fireEvent('status.get', ['active', 'snatched', 'ignored', 'done', 'downloaded'], single = True)
|
||||
# library = fireEvent('library.add.movie', single = True, attrs = params, update_after = update_library)
|
||||
info = fireEvent('movie.info', merge = True, extended = False, identifier = params.get('identifier'))
|
||||
|
||||
default_profile = fireEvent('profile.default', single = True)
|
||||
cat_id = params.get('category_id')
|
||||
|
||||
try:
|
||||
db = get_session()
|
||||
m = db.query(Media).filter_by(library_id = library.get('id')).first()
|
||||
db = get_db()
|
||||
|
||||
new = False
|
||||
try:
|
||||
m = db.get('movie', params.get('identifier'), with_doc = True)['doc']
|
||||
except:
|
||||
new = True
|
||||
m = db.insert({
|
||||
'type': 'movie',
|
||||
'identifier': params.get('identifier'),
|
||||
'status': status_id if status_id else 'active',
|
||||
'profile_id': params.get('profile_id', default_profile.get('id')),
|
||||
'category_id': tryInt(cat_id) if cat_id is not None and tryInt(cat_id) > 0 else None,
|
||||
})
|
||||
|
||||
added = True
|
||||
do_search = False
|
||||
search_after = search_after and self.conf('search_on_add', section = 'moviesearcher')
|
||||
if not m:
|
||||
m = Media(
|
||||
library_id = library.get('id'),
|
||||
profile_id = params.get('profile_id', default_profile.get('id')),
|
||||
status_id = status_id if status_id else status_active.get('id'),
|
||||
category_id = tryInt(cat_id) if cat_id is not None and tryInt(cat_id) > 0 else None,
|
||||
)
|
||||
db.add(m)
|
||||
db.commit()
|
||||
|
||||
if new:
|
||||
onComplete = None
|
||||
if search_after:
|
||||
onComplete = self.createOnComplete(m.id)
|
||||
onComplete = self.createOnComplete(m['_id'])
|
||||
|
||||
fireEventAsync('library.update.movie', params.get('identifier'), default_title = params.get('title', ''), on_complete = onComplete)
|
||||
# fireEventAsync('library.update.movie', params.get('identifier'), default_title = params.get('title', ''), on_complete = onComplete)
|
||||
search_after = False
|
||||
elif force_readd:
|
||||
|
||||
# Clean snatched history
|
||||
for release in m.releases:
|
||||
if release.status_id in [downloaded_status.get('id'), snatched_status.get('id'), done_status.get('id')]:
|
||||
for release in db.run('release', 'for_media', m['_id']):
|
||||
if release.get('status') in ['downloaded', 'snatched', 'done']:
|
||||
if params.get('ignore_previous', False):
|
||||
release.status_id = ignored_status.get('id')
|
||||
release['status'] = 'ignored'
|
||||
db.update(release)
|
||||
else:
|
||||
fireEvent('release.delete', release.id, single = True)
|
||||
fireEvent('release.delete', release['_id'], single = True)
|
||||
|
||||
m.profile_id = params.get('profile_id', default_profile.get('id'))
|
||||
m.category_id = tryInt(cat_id) if cat_id is not None and tryInt(cat_id) > 0 else (m.category_id or None)
|
||||
m['profile_id'] = params.get('profile_id', default_profile.get('id'))
|
||||
m['category_id'] = tryInt(cat_id) if cat_id is not None and tryInt(cat_id) > 0 else (m['category_id'] or None)
|
||||
else:
|
||||
log.debug('Movie already exists, not updating: %s', params)
|
||||
added = False
|
||||
|
||||
if force_readd:
|
||||
m.status_id = status_id if status_id else status_active.get('id')
|
||||
m.last_edit = int(time.time())
|
||||
m['status'] = status_id if status_id else 'active'
|
||||
m['last_edit'] = int(time.time())
|
||||
do_search = True
|
||||
|
||||
db.commit()
|
||||
db.update(m)
|
||||
|
||||
# Remove releases
|
||||
available_status = fireEvent('status.get', 'available', single = True)
|
||||
for rel in m.releases:
|
||||
if rel.status_id is available_status.get('id'):
|
||||
for rel in db.run('release', 'for_media', m['_id']):
|
||||
if rel['status'] is 'available':
|
||||
db.delete(rel)
|
||||
db.commit()
|
||||
|
||||
movie_dict = m.to_dict(self.default_dict)
|
||||
movie_dict = db.run('movie', 'to_dict', m['_id'])
|
||||
|
||||
if do_search and search_after:
|
||||
onComplete = self.createOnComplete(m.id)
|
||||
onComplete = self.createOnComplete(m['_id'])
|
||||
onComplete()
|
||||
|
||||
if added:
|
||||
if params.get('title'):
|
||||
message = 'Successfully added "%s" to your wanted list.' % params.get('title', '')
|
||||
else:
|
||||
title = getTitle(m.library)
|
||||
title = getTitle(m)
|
||||
if title:
|
||||
message = 'Successfully added "%s" to your wanted list.' % title
|
||||
else:
|
||||
@@ -142,10 +142,7 @@ class MovieBase(MovieTypeBase):
|
||||
|
||||
return movie_dict
|
||||
except:
|
||||
log.error('Failed deleting media: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
log.error('Failed adding media: %s', traceback.format_exc())
|
||||
|
||||
def addView(self, **kwargs):
|
||||
add_dict = self.add(params = kwargs)
|
||||
@@ -158,49 +155,44 @@ class MovieBase(MovieTypeBase):
|
||||
def edit(self, id = '', **kwargs):
|
||||
|
||||
try:
|
||||
db = get_session()
|
||||
|
||||
available_status = fireEvent('status.get', 'available', single = True)
|
||||
db = get_db()
|
||||
|
||||
ids = splitString(id)
|
||||
for media_id in ids:
|
||||
|
||||
m = db.query(Media).filter_by(id = media_id).first()
|
||||
if not m:
|
||||
continue
|
||||
try:
|
||||
m = db.get('media', media_id)
|
||||
m['profile_id'] = kwargs.get('profile_id')
|
||||
|
||||
m.profile_id = kwargs.get('profile_id')
|
||||
cat_id = kwargs.get('category_id')
|
||||
if cat_id is not None:
|
||||
m['category_id'] = tryInt(cat_id) if tryInt(cat_id) > 0 else None
|
||||
|
||||
cat_id = kwargs.get('category_id')
|
||||
if cat_id is not None:
|
||||
m.category_id = tryInt(cat_id) if tryInt(cat_id) > 0 else None
|
||||
# Remove releases
|
||||
for rel in db.run('release', 'for_media', m['_id']):
|
||||
if rel['status'] is 'available':
|
||||
db.delete(rel)
|
||||
|
||||
# Remove releases
|
||||
for rel in m.releases:
|
||||
if rel.status_id is available_status.get('id'):
|
||||
db.delete(rel)
|
||||
db.commit()
|
||||
# Default title
|
||||
if kwargs.get('default_title'):
|
||||
for title in m['titles']:
|
||||
title.default = toUnicode(kwargs.get('default_title', '')).lower() == toUnicode(title.title).lower()
|
||||
|
||||
# Default title
|
||||
if kwargs.get('default_title'):
|
||||
for title in m.library.titles:
|
||||
title.default = toUnicode(kwargs.get('default_title', '')).lower() == toUnicode(title.title).lower()
|
||||
db.update(m)
|
||||
|
||||
db.commit()
|
||||
fireEvent('media.restatus', m['_id'])
|
||||
|
||||
fireEvent('media.restatus', m.id)
|
||||
movie_dict = db.run('media', 'to_dict', m['_id'])
|
||||
fireEventAsync('movie.searcher.single', movie_dict, on_complete = self.createNotifyFront(media_id))
|
||||
|
||||
movie_dict = m.to_dict(self.default_dict)
|
||||
fireEventAsync('movie.searcher.single', movie_dict, on_complete = self.createNotifyFront(media_id))
|
||||
except:
|
||||
log.error('Can\'t edit non-existing media')
|
||||
|
||||
return {
|
||||
'success': True,
|
||||
}
|
||||
except:
|
||||
log.error('Failed deleting media: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
log.error('Failed editing media: %s', traceback.format_exc())
|
||||
|
||||
return {
|
||||
'success': False,
|
||||
|
||||
@@ -62,7 +62,7 @@ class MovieLibraryPlugin(LibraryBase):
|
||||
log.error('Failed adding media: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
return {}
|
||||
|
||||
@@ -130,31 +130,24 @@ class MovieLibraryPlugin(LibraryBase):
|
||||
|
||||
# Files
|
||||
images = info.get('images', [])
|
||||
library['files'] = []
|
||||
for image_type in ['poster']:
|
||||
for image in images.get(image_type, []):
|
||||
if not isinstance(image, (str, unicode)):
|
||||
continue
|
||||
|
||||
file_path = fireEvent('file.download', url = image, single = True)
|
||||
if file_path:
|
||||
file_obj = fireEvent('file.add', path = file_path, type_tuple = ('image', image_type), single = True)
|
||||
try:
|
||||
file_obj = db.query(File).filter_by(id = file_obj.get('id')).one()
|
||||
library.files.append(file_obj)
|
||||
db.commit()
|
||||
|
||||
break
|
||||
except:
|
||||
log.debug('Failed to attach to library: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
# TODO: save in movie doc
|
||||
library['files'].append({
|
||||
'type': 'image_%s' % image_type,
|
||||
'path': file_path
|
||||
})
|
||||
|
||||
library_dict = library.to_dict(self.default_dict)
|
||||
return library_dict
|
||||
except:
|
||||
log.error('Failed update media: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
return {}
|
||||
|
||||
@@ -180,7 +173,7 @@ class MovieLibraryPlugin(LibraryBase):
|
||||
log.error('Failed updating release dates: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
return {}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from couchpotato import get_session
|
||||
from couchpotato import get_session, get_db
|
||||
from couchpotato.api import addApiView
|
||||
from couchpotato.core.event import addEvent, fireEvent, fireEventAsync
|
||||
from couchpotato.core.helpers.encoding import simplifyString
|
||||
@@ -51,7 +51,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
|
||||
})
|
||||
|
||||
if self.conf('run_on_launch'):
|
||||
addEvent('app.load', self.searchAll)
|
||||
addEvent('app.load2', self.searchAll)
|
||||
|
||||
def searchAllView(self, **kwargs):
|
||||
|
||||
@@ -71,27 +71,16 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
|
||||
self.in_progress = True
|
||||
fireEvent('notify.frontend', type = 'movie.searcher.started', data = True, message = 'Full search started')
|
||||
|
||||
db = get_session()
|
||||
db = get_db()
|
||||
|
||||
movies_raw = db.query(Media).filter(
|
||||
Media.status.has(identifier = 'active')
|
||||
).all()
|
||||
movies = db.get_many('movie_status', 'active')
|
||||
|
||||
random.shuffle(movies_raw)
|
||||
|
||||
movies = []
|
||||
for m in movies_raw:
|
||||
movies.append(m.to_dict({
|
||||
'category': {},
|
||||
'profile': {'types': {'quality': {}}},
|
||||
'releases': {'status': {}, 'quality': {}},
|
||||
'library': {'titles': {}, 'files': {}},
|
||||
'files': {},
|
||||
}))
|
||||
#TODO: random.shuffle(movies_raw)
|
||||
|
||||
total = db.count(db.get_many, 'movie_status', 'active')
|
||||
self.in_progress = {
|
||||
'total': len(movies),
|
||||
'to_go': len(movies),
|
||||
'total': total,
|
||||
'to_go': total,
|
||||
}
|
||||
|
||||
try:
|
||||
@@ -99,13 +88,15 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
|
||||
|
||||
for movie in movies:
|
||||
|
||||
movie_dict = db.run('media', 'to_dict', movie['_id'])
|
||||
|
||||
try:
|
||||
self.single(movie, search_protocols)
|
||||
self.single(movie_dict, search_protocols)
|
||||
except IndexError:
|
||||
log.error('Forcing library update for %s, if you see this often, please report: %s', (movie['library']['identifier'], traceback.format_exc()))
|
||||
fireEvent('library.update.movie', movie['library']['identifier'])
|
||||
log.error('Forcing library update for %s, if you see this often, please report: %s', (movie['identifier'], traceback.format_exc()))
|
||||
fireEvent('library.update.movie', movie['identifier'])
|
||||
except:
|
||||
log.error('Search failed for %s: %s', (movie['library']['identifier'], traceback.format_exc()))
|
||||
log.error('Search failed for %s: %s', (movie['identifier'], traceback.format_exc()))
|
||||
|
||||
self.in_progress['to_go'] -= 1
|
||||
|
||||
@@ -117,7 +108,6 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
|
||||
pass
|
||||
|
||||
self.in_progress = False
|
||||
db.close()
|
||||
|
||||
def single(self, movie, search_protocols = None, manual = False):
|
||||
|
||||
@@ -132,32 +122,30 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
|
||||
except SearchSetupError:
|
||||
return
|
||||
|
||||
done_status = fireEvent('status.get', 'done', single = True)
|
||||
|
||||
if not movie['profile'] or (movie['status_id'] == done_status.get('id') and not manual):
|
||||
if not movie['profile_id'] or (movie['status'] == 'done' and not manual):
|
||||
log.debug('Movie doesn\'t have a profile or already done, assuming in manage tab.')
|
||||
return
|
||||
|
||||
pre_releases = fireEvent('quality.pre_releases', single = True)
|
||||
release_dates = fireEvent('library.update.movie.release_date', identifier = movie['library']['identifier'], merge = True)
|
||||
available_status, ignored_status, failed_status = fireEvent('status.get', ['available', 'ignored', 'failed'], single = True)
|
||||
|
||||
found_releases = []
|
||||
too_early_to_search = []
|
||||
|
||||
default_title = getTitle(movie['library'])
|
||||
default_title = getTitle(movie)
|
||||
if not default_title:
|
||||
log.error('No proper info found for movie, removing it from library to cause it from having more issues.')
|
||||
fireEvent('media.delete', movie['id'], single = True)
|
||||
fireEvent('media.delete', movie['_id'], single = True)
|
||||
return
|
||||
|
||||
fireEvent('notify.frontend', type = 'movie.searcher.started', data = {'id': movie['id']}, message = 'Searching for "%s"' % default_title)
|
||||
fireEvent('notify.frontend', type = 'movie.searcher.started', data = {'id': movie['_id']}, message = 'Searching for "%s"' % default_title)
|
||||
|
||||
db = get_session()
|
||||
db = get_db()
|
||||
|
||||
ret = False
|
||||
|
||||
for quality_type in movie['profile']['types']:
|
||||
if not self.conf('always_search') and not self.couldBeReleased(quality_type['quality']['identifier'] in pre_releases, release_dates, movie['library']['year']):
|
||||
if not self.conf('always_search') and not self.couldBeReleased(quality_type['quality']['identifier'] in pre_releases, release_dates, movie['year']):
|
||||
too_early_to_search.append(quality_type['quality']['identifier'])
|
||||
continue
|
||||
|
||||
@@ -165,7 +153,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
|
||||
|
||||
# See if better quality is available
|
||||
for release in movie['releases']:
|
||||
if release['quality']['order'] <= quality_type['quality']['order'] and release['status_id'] not in [available_status.get('id'), ignored_status.get('id'), failed_status.get('id')]:
|
||||
if release['quality']['order'] <= quality_type['quality']['order'] and release['status'] not in ['available', 'ignored', 'failed']:
|
||||
has_better_quality += 1
|
||||
|
||||
# Don't search for quality lower then already available.
|
||||
@@ -179,7 +167,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
|
||||
log.debug('Nothing found for %s in %s', (default_title, quality_type['quality']['label']))
|
||||
|
||||
# Check if movie isn't deleted while searching
|
||||
if not db.query(Media).filter_by(id = movie.get('id')).first():
|
||||
if not fireEvent('media.get', movie.get('_id'), single = True):
|
||||
break
|
||||
|
||||
# Add them to this movie releases list
|
||||
@@ -191,12 +179,12 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
|
||||
|
||||
# Remove releases that aren't found anymore
|
||||
for release in movie.get('releases', []):
|
||||
if release.get('status_id') == available_status.get('id') and release.get('identifier') not in found_releases:
|
||||
fireEvent('release.delete', release.get('id'), single = True)
|
||||
if release.get('status') == 'available' and release.get('identifier') not in found_releases:
|
||||
fireEvent('release.delete', release.get('_id'), single = True)
|
||||
|
||||
else:
|
||||
log.info('Better quality (%s) already available or snatched for %s', (quality_type['quality']['label'], default_title))
|
||||
fireEvent('media.restatus', movie['id'])
|
||||
fireEvent('media.restatus', movie['_id'])
|
||||
break
|
||||
|
||||
# Break if CP wants to shut down
|
||||
@@ -206,9 +194,9 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
|
||||
if len(too_early_to_search) > 0:
|
||||
log.info2('Too early to search for %s, %s', (too_early_to_search, default_title))
|
||||
|
||||
fireEvent('notify.frontend', type = 'movie.searcher.ended', data = {'id': movie['id']})
|
||||
fireEvent('notify.frontend', type = 'movie.searcher.ended', data = {'id': movie['_id']})
|
||||
|
||||
db.close()
|
||||
pass #db.close()
|
||||
return ret
|
||||
|
||||
def correctRelease(self, nzb = None, media = None, quality = None, **kwargs):
|
||||
@@ -329,31 +317,23 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
|
||||
|
||||
def tryNextRelease(self, media_id, manual = False):
|
||||
|
||||
snatched_status, done_status, ignored_status = fireEvent('status.get', ['snatched', 'done', 'ignored'], single = True)
|
||||
|
||||
try:
|
||||
db = get_session()
|
||||
rels = db.query(Release) \
|
||||
.filter_by(movie_id = media_id) \
|
||||
.filter(Release.status_id.in_([snatched_status.get('id'), done_status.get('id')])) \
|
||||
.all()
|
||||
db = get_db()
|
||||
rels = db.run('media', 'with_status', media_id, status = ['snatched', 'done'])
|
||||
|
||||
for rel in rels:
|
||||
rel.status_id = ignored_status.get('id')
|
||||
db.commit()
|
||||
rel['status'] = 'ignored'
|
||||
db.update(rel)
|
||||
|
||||
movie_dict = fireEvent('media.get', media_id = media_id, single = True)
|
||||
log.info('Trying next release for: %s', getTitle(movie_dict['library']))
|
||||
fireEvent('movie.searcher.single', movie_dict, manual = manual)
|
||||
movie_dict = db.run('media', 'to_dict', media_id)
|
||||
log.info('Trying next release for: %s', getTitle(movie_dict))
|
||||
self.single(movie_dict, manual = manual)
|
||||
|
||||
return True
|
||||
|
||||
except:
|
||||
log.error('Failed searching for next release: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
return False
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
def getSearchTitle(self, media):
|
||||
if media['type'] == 'movie':
|
||||
|
||||
@@ -33,7 +33,7 @@ class Suggestion(Plugin):
|
||||
.options(joinedload_all('library')) \
|
||||
.filter(or_(*[Media.status.has(identifier = s) for s in ['active', 'done']])).all()
|
||||
movies = [x.library.identifier for x in active_movies]
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
if not ignored or len(ignored) == 0:
|
||||
ignored = splitString(Env.prop('suggest_ignore', default = ''))
|
||||
@@ -98,7 +98,7 @@ class Suggestion(Plugin):
|
||||
.filter(Media.status_id.in_([active_status.get('id'), done_status.get('id')])).all()
|
||||
movies = [x[0] for x in active_movies]
|
||||
movies.extend(seen)
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
ignored.extend([x.get('imdb') for x in cached_suggestion])
|
||||
suggestions = fireEvent('movie.suggest', movies = movies, ignore = removeDuplicate(ignored), single = True)
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import time
|
||||
from CodernityDB.tree_index import TreeBasedIndex
|
||||
|
||||
|
||||
class NotificationIndex(TreeBasedIndex):
|
||||
|
||||
custom_header = """from CodernityDB.tree_index import TreeBasedIndex
|
||||
import time"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['key_format'] = 'I'
|
||||
super(NotificationIndex, self).__init__(*args, **kwargs)
|
||||
|
||||
def make_key(self, key):
|
||||
return key
|
||||
|
||||
def make_key_value(self, data):
|
||||
if data.get('type') == 'notification':
|
||||
added = data.get('added', time.time())
|
||||
data['added'] = added
|
||||
|
||||
return added, None
|
||||
|
||||
|
||||
class NotificationUnreadIndex(TreeBasedIndex):
|
||||
|
||||
custom_header = """from CodernityDB.tree_index import TreeBasedIndex
|
||||
import time"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['key_format'] = 'I'
|
||||
super(NotificationUnreadIndex, self).__init__(*args, **kwargs)
|
||||
|
||||
def make_key(self, key):
|
||||
return key
|
||||
|
||||
def make_key_value(self, data):
|
||||
if data.get('type') == 'notification' and not data.get('read'):
|
||||
added = data.get('added', time.time())
|
||||
data['added'] = added
|
||||
|
||||
return added, None
|
||||
@@ -1,14 +1,13 @@
|
||||
from couchpotato import get_session
|
||||
from couchpotato import get_db
|
||||
from couchpotato.api import addApiView, addNonBlockApiView
|
||||
from couchpotato.core.event import addEvent, fireEvent
|
||||
from couchpotato.core.helpers.encoding import toUnicode
|
||||
from couchpotato.core.helpers.variable import tryInt, splitString
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.notifications.base import Notification
|
||||
from couchpotato.core.settings.model import Notification as Notif
|
||||
from .index import NotificationIndex, NotificationUnreadIndex
|
||||
from couchpotato.environment import Env
|
||||
from operator import itemgetter
|
||||
from sqlalchemy.sql.expression import or_
|
||||
import threading
|
||||
import time
|
||||
import traceback
|
||||
@@ -58,48 +57,55 @@ class CoreNotifier(Notification):
|
||||
fireEvent('schedule.interval', 'core.check_messages', self.checkMessages, hours = 12, single = True)
|
||||
fireEvent('schedule.interval', 'core.clean_messages', self.cleanMessages, seconds = 15, single = True)
|
||||
|
||||
addEvent('app.load', self.clean)
|
||||
addEvent('app.load', self.checkMessages)
|
||||
addEvent('app.load2', self.clean)
|
||||
addEvent('app.load2', self.checkMessages)
|
||||
|
||||
addEvent('database.setup', self.databaseSetup)
|
||||
|
||||
self.messages = []
|
||||
self.listeners = []
|
||||
self.m_lock = threading.Lock()
|
||||
|
||||
def clean(self):
|
||||
def databaseSetup(self):
|
||||
|
||||
db = get_db()
|
||||
|
||||
try:
|
||||
db = get_session()
|
||||
db.query(Notif).filter(Notif.added <= (int(time.time()) - 2419200)).delete()
|
||||
db.commit()
|
||||
db.add_index(NotificationIndex(db.path, 'notification'))
|
||||
except:
|
||||
log.debug('Index already exists')
|
||||
db.edit_index(NotificationIndex(db.path, 'notification'))
|
||||
|
||||
try:
|
||||
db.add_index(NotificationUnreadIndex(db.path, 'notification_unread'))
|
||||
except:
|
||||
log.debug('Index already exists')
|
||||
db.edit_index(NotificationUnreadIndex(db.path, 'notification_unread'))
|
||||
|
||||
def clean(self):
|
||||
try:
|
||||
db = get_db()
|
||||
for n in db.all('notification', with_doc = True):
|
||||
if n['doc']['added'] <= (int(time.time()) - 2419200):
|
||||
db.delete(n['doc'])
|
||||
except:
|
||||
log.error('Failed cleaning notification: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
def markAsRead(self, ids = None, **kwargs):
|
||||
|
||||
ids = splitString(ids) if ids else None
|
||||
|
||||
try:
|
||||
db = get_session()
|
||||
|
||||
if ids:
|
||||
q = db.query(Notif).filter(or_(*[Notif.id == tryInt(s) for s in ids]))
|
||||
else:
|
||||
q = db.query(Notif).filter_by(read = False)
|
||||
|
||||
q.update({Notif.read: True})
|
||||
db.commit()
|
||||
|
||||
db = get_db()
|
||||
for x in db.all('notification_unread', with_doc = True):
|
||||
if not ids or x['_id'] in ids:
|
||||
x['doc']['read'] = True
|
||||
db.update(x['doc'])
|
||||
return {
|
||||
'success': True
|
||||
}
|
||||
except:
|
||||
log.error('Failed mark as read: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
return {
|
||||
'success': False
|
||||
@@ -107,26 +113,20 @@ class CoreNotifier(Notification):
|
||||
|
||||
def listView(self, limit_offset = None, **kwargs):
|
||||
|
||||
db = get_session()
|
||||
|
||||
q = db.query(Notif)
|
||||
db = get_db()
|
||||
|
||||
if limit_offset:
|
||||
splt = splitString(limit_offset)
|
||||
limit = splt[0]
|
||||
offset = 0 if len(splt) is 1 else splt[1]
|
||||
q = q.limit(limit).offset(offset)
|
||||
results = db.get_many('notification', limit = limit, offset = offset, with_doc = True)
|
||||
else:
|
||||
q = q.limit(200)
|
||||
results = db.get_many('notification', limit = 200, with_doc = True)
|
||||
|
||||
results = q.all()
|
||||
notifications = []
|
||||
for n in results:
|
||||
ndict = n.to_dict()
|
||||
ndict['type'] = 'notification'
|
||||
notifications.append(ndict)
|
||||
notifications.append(n['doc'])
|
||||
|
||||
db.close()
|
||||
return {
|
||||
'success': True,
|
||||
'empty': len(notifications) == 0,
|
||||
@@ -156,30 +156,23 @@ class CoreNotifier(Notification):
|
||||
if not data: data = {}
|
||||
|
||||
try:
|
||||
db = get_session()
|
||||
db = get_db()
|
||||
|
||||
data['notification_type'] = listener if listener else 'unknown'
|
||||
|
||||
n = Notif(
|
||||
message = toUnicode(message),
|
||||
data = data
|
||||
)
|
||||
db.add(n)
|
||||
db.commit()
|
||||
n = {
|
||||
'type': 'notification',
|
||||
'time': time.time(),
|
||||
'message': toUnicode(message),
|
||||
'data': data
|
||||
}
|
||||
db.insert(n)
|
||||
|
||||
ndict = n.to_dict()
|
||||
ndict['type'] = 'notification'
|
||||
ndict['time'] = time.time()
|
||||
self.frontend(type = listener, data = n)
|
||||
|
||||
self.frontend(type = listener, data = data)
|
||||
|
||||
db.close()
|
||||
return True
|
||||
except:
|
||||
log.error('Failed notify: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
def frontend(self, type = 'notification', data = None, message = None):
|
||||
if not data: data = {}
|
||||
@@ -278,18 +271,13 @@ class CoreNotifier(Notification):
|
||||
|
||||
# Get unread
|
||||
if init:
|
||||
db = get_session()
|
||||
db = get_db()
|
||||
|
||||
notifications = db.query(Notif) \
|
||||
.filter(or_(Notif.read == False, Notif.added > (time.time() - 259200))) \
|
||||
.all()
|
||||
notifications = db.all('notification_unread', with_doc = True)
|
||||
|
||||
for n in notifications:
|
||||
ndict = n.to_dict()
|
||||
ndict['type'] = 'notification'
|
||||
messages.append(ndict)
|
||||
|
||||
db.close()
|
||||
if n['doc'].get('added') > (time.time() - 259200):
|
||||
messages.append(n['doc'])
|
||||
|
||||
return {
|
||||
'success': True,
|
||||
|
||||
@@ -16,7 +16,7 @@ class Growl(Notification):
|
||||
super(Growl, self).__init__()
|
||||
|
||||
if self.isEnabled():
|
||||
addEvent('app.load', self.register)
|
||||
addEvent('app.load2', self.register)
|
||||
|
||||
def register(self):
|
||||
if self.registered: return
|
||||
|
||||
@@ -10,10 +10,10 @@ class Automation(Plugin):
|
||||
|
||||
def __init__(self):
|
||||
|
||||
addEvent('app.load', self.setCrons)
|
||||
addEvent('app.load2', self.setCrons)
|
||||
|
||||
if not Env.get('dev'):
|
||||
addEvent('app.load', self.addMovies)
|
||||
addEvent('app.load2', self.addMovies)
|
||||
|
||||
addEvent('setting.save.automation.hour.after', self.setCrons)
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ class CategoryPlugin(Plugin):
|
||||
for category in categories:
|
||||
temp.append(category.to_dict())
|
||||
|
||||
db.close()
|
||||
pass #db.close()
|
||||
return temp
|
||||
|
||||
def save(self, **kwargs):
|
||||
@@ -66,7 +66,7 @@ class CategoryPlugin(Plugin):
|
||||
|
||||
category_dict = c.to_dict()
|
||||
|
||||
db.close()
|
||||
pass #db.close()
|
||||
return {
|
||||
'success': True,
|
||||
'category': category_dict
|
||||
@@ -75,7 +75,7 @@ class CategoryPlugin(Plugin):
|
||||
log.error('Failed: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
return {
|
||||
'success': False,
|
||||
@@ -96,7 +96,7 @@ class CategoryPlugin(Plugin):
|
||||
|
||||
db.commit()
|
||||
|
||||
db.close()
|
||||
pass #db.close()
|
||||
return {
|
||||
'success': True
|
||||
}
|
||||
@@ -104,7 +104,7 @@ class CategoryPlugin(Plugin):
|
||||
log.error('Failed: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
return {
|
||||
'success': False
|
||||
@@ -129,7 +129,7 @@ class CategoryPlugin(Plugin):
|
||||
except Exception as e:
|
||||
message = log.error('Failed deleting category: %s', e)
|
||||
|
||||
db.close()
|
||||
pass #db.close()
|
||||
return {
|
||||
'success': success,
|
||||
'message': message
|
||||
@@ -138,7 +138,7 @@ class CategoryPlugin(Plugin):
|
||||
log.error('Failed: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
return {
|
||||
'success': False
|
||||
@@ -158,4 +158,4 @@ class CategoryPlugin(Plugin):
|
||||
log.error('Failed: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
pass #db.close()
|
||||
@@ -10,7 +10,7 @@ log = CPLog(__name__)
|
||||
class Custom(Plugin):
|
||||
|
||||
def __init__(self):
|
||||
addEvent('app.load', self.createStructure)
|
||||
addEvent('app.load2', self.createStructure)
|
||||
|
||||
def createStructure(self):
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ class Dashboard(Plugin):
|
||||
'files': {},
|
||||
}))
|
||||
|
||||
db.close()
|
||||
pass #db.close()
|
||||
return {
|
||||
'success': True,
|
||||
'empty': len(movies) == 0,
|
||||
|
||||
@@ -19,9 +19,7 @@ log = CPLog(__name__)
|
||||
class FileManager(Plugin):
|
||||
|
||||
def __init__(self):
|
||||
addEvent('file.add', self.add)
|
||||
addEvent('file.download', self.download)
|
||||
addEvent('file.types', self.getTypes)
|
||||
|
||||
addApiView('file.cache/(.*)', self.showCacheFile, static = True, docs = {
|
||||
'desc': 'Return a file from the cp_data/cache directory',
|
||||
@@ -31,36 +29,8 @@ class FileManager(Plugin):
|
||||
'return': {'type': 'file'}
|
||||
})
|
||||
|
||||
addApiView('file.types', self.getTypesView, docs = {
|
||||
'desc': 'Return a list of all the file types and their ids.',
|
||||
'return': {'type': 'object', 'example': """{
|
||||
'types': [
|
||||
{
|
||||
"identifier": "poster_original",
|
||||
"type": "image",
|
||||
"id": 1,
|
||||
"name": "Poster_original"
|
||||
},
|
||||
{
|
||||
"identifier": "poster",
|
||||
"type": "image",
|
||||
"id": 2,
|
||||
"name": "Poster"
|
||||
},
|
||||
etc
|
||||
]
|
||||
}"""}
|
||||
})
|
||||
|
||||
addEvent('app.load', self.cleanup)
|
||||
addEvent('app.load', self.init)
|
||||
|
||||
def init(self):
|
||||
|
||||
for type_tuple in Scanner.file_types.values():
|
||||
self.getType(type_tuple)
|
||||
|
||||
def cleanup(self):
|
||||
# TODO: unused
|
||||
|
||||
# Wait a bit after starting before cleanup
|
||||
time.sleep(3)
|
||||
@@ -77,9 +47,6 @@ class FileManager(Plugin):
|
||||
os.remove(file_path)
|
||||
except:
|
||||
log.error('Failed removing unused file: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
def showCacheFile(self, route, **kwargs):
|
||||
Env.get('app').add_handlers(".*$", [('%s%s' % (Env.get('api_base'), route), StaticFileHandler, {'path': Env.get('cache_dir')})])
|
||||
@@ -101,76 +68,3 @@ class FileManager(Plugin):
|
||||
|
||||
self.createFile(dest, filedata, binary = True)
|
||||
return dest
|
||||
|
||||
def add(self, path = '', part = 1, type_tuple = (), available = 1, properties = None):
|
||||
if not properties: properties = {}
|
||||
|
||||
try:
|
||||
db = get_session()
|
||||
type_id = self.getType(type_tuple).get('id')
|
||||
|
||||
f = db.query(File).filter(File.path == toUnicode(path)).first()
|
||||
if not f:
|
||||
f = File()
|
||||
db.add(f)
|
||||
|
||||
f.path = toUnicode(path)
|
||||
f.part = part
|
||||
f.available = available
|
||||
f.type_id = type_id
|
||||
|
||||
db.commit()
|
||||
|
||||
file_dict = f.to_dict()
|
||||
|
||||
return file_dict
|
||||
except:
|
||||
log.error('Failed adding file: %s, %s', (path, traceback.format_exc()))
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
def getType(self, type_tuple):
|
||||
|
||||
try:
|
||||
db = get_session()
|
||||
type_type, type_identifier = type_tuple
|
||||
|
||||
ft = db.query(FileType).filter_by(identifier = type_identifier).first()
|
||||
if not ft:
|
||||
ft = FileType(
|
||||
type = toUnicode(type_type),
|
||||
identifier = type_identifier,
|
||||
name = toUnicode(type_identifier[0].capitalize() + type_identifier[1:])
|
||||
)
|
||||
db.add(ft)
|
||||
db.commit()
|
||||
|
||||
type_dict = ft.to_dict()
|
||||
|
||||
return type_dict
|
||||
except:
|
||||
log.error('Failed getting type: %s, %s', (type_tuple, traceback.format_exc()))
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
def getTypes(self):
|
||||
|
||||
db = get_session()
|
||||
|
||||
results = db.query(FileType).all()
|
||||
|
||||
types = []
|
||||
for type_object in results:
|
||||
types.append(type_object.to_dict())
|
||||
|
||||
db.close()
|
||||
return types
|
||||
|
||||
def getTypesView(self, **kwargs):
|
||||
|
||||
return {
|
||||
'types': self.getTypes()
|
||||
}
|
||||
@@ -47,7 +47,7 @@ class Manage(Plugin):
|
||||
})
|
||||
|
||||
if not Env.get('dev') and self.conf('startup_scan'):
|
||||
addEvent('app.load', self.updateLibraryQuick)
|
||||
addEvent('app.load2', self.updateLibraryQuick)
|
||||
|
||||
def getProgress(self, **kwargs):
|
||||
return {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
from .main import NoSQL
|
||||
|
||||
|
||||
def start():
|
||||
return NoSQL()
|
||||
|
||||
config = []
|
||||
@@ -0,0 +1,20 @@
|
||||
from hashlib import md5
|
||||
from CodernityDB.tree_index import TreeBasedIndex
|
||||
|
||||
|
||||
class ReleaseIndex(TreeBasedIndex):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['key_format'] = '16s'
|
||||
super(ReleaseIndex, self).__init__(*args, **kwargs)
|
||||
|
||||
def make_key(self, key):
|
||||
return md5(key).digest()
|
||||
|
||||
def make_key_value(self, data):
|
||||
if data.get('type') == 'release':
|
||||
return md5(data['media_id']).digest(), None
|
||||
|
||||
def run_for_media(self, db, media_id):
|
||||
for release in db.get_many('release', media_id, with_doc=True):
|
||||
yield release['doc']
|
||||
@@ -0,0 +1,72 @@
|
||||
import time
|
||||
from couchpotato import CPLog
|
||||
from couchpotato.core.plugins.base import Plugin
|
||||
from .index import ReleaseIndex, MediaIMDBIndex, TitleIndex
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class NoSQL(Plugin):
|
||||
|
||||
db = None
|
||||
|
||||
def test(self):
|
||||
|
||||
db = self.db
|
||||
|
||||
try: db.add_index(ReleaseIndex(db.path, 'release'))
|
||||
except: log.debug('Index already exists')
|
||||
|
||||
for id in range(10):
|
||||
media = db.insert({
|
||||
'type': 'media',
|
||||
'tmdb': id,
|
||||
'imdb': 'tt%s' % id,
|
||||
'last_edit': 0,
|
||||
'status': 'active',
|
||||
'title': 'Lord of the Rings: The Return of the King',
|
||||
'year': 2011,
|
||||
'profile_id': 0,
|
||||
'category_id': 0,
|
||||
})
|
||||
|
||||
db.insert({
|
||||
'media_id': media['_id'],
|
||||
'type': 'title',
|
||||
'title': 'Lord of the Rings: The Return of the King',
|
||||
})
|
||||
|
||||
for x in range(40):
|
||||
db.insert({
|
||||
'media_id': media['_id'],
|
||||
'type': 'release',
|
||||
'name': 'Release %s' % x
|
||||
})
|
||||
|
||||
print db.count(db.all, 'media')
|
||||
|
||||
m = db.get('media', 'tt0')
|
||||
db.get('id', m['_id'])
|
||||
|
||||
start = time.time()
|
||||
print list(db.get_many('media_title', 'lord of'))
|
||||
print time.time() - start
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
for media in db.all('media', with_doc = True):
|
||||
doc = media['doc']
|
||||
for r in db.run('release', 'for_media', media['_id']):
|
||||
db.delete(r)
|
||||
|
||||
db.delete(doc)
|
||||
break
|
||||
|
||||
start = time.time()
|
||||
db.reindex()
|
||||
print time.time() - start
|
||||
|
||||
print db.count(db.all, 'media')
|
||||
print db.count(db.all, 'release')
|
||||
@@ -1,5 +1,5 @@
|
||||
import traceback
|
||||
from couchpotato import get_session
|
||||
from couchpotato import get_session, get_db
|
||||
from couchpotato.api import addApiView
|
||||
from couchpotato.core.event import addEvent, fireEvent
|
||||
from couchpotato.core.helpers.encoding import toUnicode
|
||||
@@ -31,27 +31,24 @@ class ProfilePlugin(Plugin):
|
||||
})
|
||||
|
||||
addEvent('app.initialize', self.fill, priority = 90)
|
||||
addEvent('app.load', self.forceDefaults)
|
||||
addEvent('app.load2', self.forceDefaults)
|
||||
|
||||
def forceDefaults(self):
|
||||
|
||||
# Get all active movies without profile
|
||||
active_status = fireEvent('status.get', 'active', single = True)
|
||||
|
||||
try:
|
||||
db = get_session()
|
||||
movies = db.query(Media).filter(Media.status_id == active_status.get('id'), Media.profile == None).all()
|
||||
db = get_db()
|
||||
medias = db.run('media', 'with_status', ['active'])
|
||||
|
||||
if len(movies) > 0:
|
||||
default_profile = self.default()
|
||||
for movie in movies:
|
||||
movie.profile_id = default_profile.get('id')
|
||||
db.commit()
|
||||
profile_ids = [x.get('_id') for x in self.all()]
|
||||
|
||||
for media in medias:
|
||||
if media['profile_id'] not in profile_ids:
|
||||
default_profile = self.default()
|
||||
media['profile_id'] = default_profile.get('id')
|
||||
db.update(media)
|
||||
except:
|
||||
log.error('Failed: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
def allView(self, **kwargs):
|
||||
|
||||
@@ -62,17 +59,10 @@ class ProfilePlugin(Plugin):
|
||||
|
||||
def all(self):
|
||||
|
||||
db = get_session()
|
||||
profiles = db.query(Profile) \
|
||||
.options(joinedload_all('types')) \
|
||||
.all()
|
||||
db = get_db()
|
||||
profiles = db.all('profile', with_doc = True)
|
||||
|
||||
temp = []
|
||||
for profile in profiles:
|
||||
temp.append(profile.to_dict(self.to_dict))
|
||||
|
||||
db.close()
|
||||
return temp
|
||||
return list(profiles)
|
||||
|
||||
def save(self, **kwargs):
|
||||
|
||||
@@ -115,7 +105,7 @@ class ProfilePlugin(Plugin):
|
||||
log.error('Failed: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
return {
|
||||
'success': False
|
||||
@@ -128,7 +118,7 @@ class ProfilePlugin(Plugin):
|
||||
.options(joinedload_all('types')) \
|
||||
.first()
|
||||
default_dict = default.to_dict(self.to_dict)
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
return default_dict
|
||||
|
||||
@@ -154,7 +144,7 @@ class ProfilePlugin(Plugin):
|
||||
log.error('Failed: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
return {
|
||||
'success': False
|
||||
@@ -188,7 +178,7 @@ class ProfilePlugin(Plugin):
|
||||
log.error('Failed: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
return {
|
||||
'success': False
|
||||
@@ -243,6 +233,6 @@ class ProfilePlugin(Plugin):
|
||||
log.error('Failed: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
return False
|
||||
@@ -79,7 +79,7 @@ class QualityPlugin(Plugin):
|
||||
|
||||
self.cached_qualities = temp
|
||||
|
||||
db.close()
|
||||
pass #db.close()
|
||||
return temp
|
||||
|
||||
def single(self, identifier = ''):
|
||||
@@ -91,7 +91,7 @@ class QualityPlugin(Plugin):
|
||||
if quality:
|
||||
quality_dict = dict(self.getQuality(quality.identifier), **quality.to_dict())
|
||||
|
||||
db.close()
|
||||
pass #db.close()
|
||||
return quality_dict
|
||||
|
||||
def getQuality(self, identifier):
|
||||
@@ -119,7 +119,7 @@ class QualityPlugin(Plugin):
|
||||
log.error('Failed: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
return {
|
||||
'success': False
|
||||
@@ -181,7 +181,7 @@ class QualityPlugin(Plugin):
|
||||
log.error('Failed: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
return False
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from couchpotato import get_session, md5
|
||||
from couchpotato import get_session, md5, get_db
|
||||
from couchpotato.api import addApiView
|
||||
from couchpotato.core.event import fireEvent, addEvent
|
||||
from couchpotato.core.helpers.encoding import ss, toUnicode
|
||||
@@ -72,34 +72,32 @@ class Release(Plugin):
|
||||
done_status, available_status, snatched_status, downloaded_status, ignored_status = \
|
||||
fireEvent('status.get', ['done', 'available', 'snatched', 'downloaded', 'ignored'], single = True)
|
||||
|
||||
db = get_session()
|
||||
db = get_db()
|
||||
|
||||
# get movies last_edit more than a week ago
|
||||
media = db.query(Media) \
|
||||
.filter(Media.status_id == done_status.get('id'), Media.last_edit < (now - week)) \
|
||||
.all()
|
||||
medias = db.run('media', 'with_status', ['done'])
|
||||
|
||||
for item in media:
|
||||
for rel in item.releases:
|
||||
for media in medias:
|
||||
if media['last_edit'] > (now - week):
|
||||
continue
|
||||
|
||||
for rel in db.run('release', 'for_media', media['_id']):
|
||||
# Remove all available releases
|
||||
if rel.status_id in [available_status.get('id')]:
|
||||
fireEvent('release.delete', id = rel.id, single = True)
|
||||
# Set all snatched and downloaded releases to ignored to make sure they are ignored when re-adding the move
|
||||
elif rel.status_id in [snatched_status.get('id'), downloaded_status.get('id')]:
|
||||
self.updateStatus(id = rel.id, status = ignored_status)
|
||||
if rel['status'] in ['available']:
|
||||
fireEvent('release.delete', id = rel['_id'], single = True)
|
||||
|
||||
db.close()
|
||||
# Set all snatched and downloaded releases to ignored to make sure they are ignored when re-adding the move
|
||||
elif rel['status'] in ['snatched', 'downloaded']:
|
||||
self.updateStatus(id = rel['id'], status = ignored_status)
|
||||
|
||||
|
||||
def add(self, group):
|
||||
|
||||
try:
|
||||
db = get_session()
|
||||
db = get_db()
|
||||
|
||||
identifier = '%s.%s.%s' % (group['library']['identifier'], group['meta_data'].get('audio', 'unknown'), group['meta_data']['quality']['identifier'])
|
||||
|
||||
done_status, snatched_status = fireEvent('status.get', ['done', 'snatched'], single = True)
|
||||
|
||||
# Add movie
|
||||
media = db.query(Media).filter_by(library_id = group['library'].get('id')).first()
|
||||
if not media:
|
||||
@@ -129,41 +127,28 @@ class Release(Plugin):
|
||||
db.commit()
|
||||
|
||||
# Add each file type
|
||||
added_files = []
|
||||
rel['files'] = []
|
||||
for type in group['files']:
|
||||
for cur_file in group['files'][type]:
|
||||
added_file = self.saveFile(cur_file, type = type, include_media_info = type is 'movie')
|
||||
added_files.append(added_file.get('id'))
|
||||
added_file = self.saveFile(cur_file, type = type)
|
||||
rel['files'].append(added_file.get('id'))
|
||||
|
||||
# Add the release files in batch
|
||||
try:
|
||||
added_files = db.query(File).filter(or_(*[File.id == x for x in added_files])).all()
|
||||
rel.files.extend(added_files)
|
||||
db.commit()
|
||||
except:
|
||||
log.debug('Failed to attach "%s" to release: %s', (added_files, traceback.format_exc()))
|
||||
|
||||
fireEvent('media.restatus', media.id)
|
||||
fireEvent('media.restatus', media['_id'])
|
||||
|
||||
return True
|
||||
except:
|
||||
log.error('Failed: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
return False
|
||||
|
||||
def saveFile(self, filepath, type = 'unknown', include_media_info = False):
|
||||
|
||||
properties = {}
|
||||
|
||||
# Get media info for files
|
||||
if include_media_info:
|
||||
properties = {}
|
||||
|
||||
# Check database and update/insert if necessary
|
||||
return fireEvent('file.add', path = filepath, part = fireEvent('scanner.partnumber', file, single = True), type_tuple = Scanner.file_types.get(type), properties = properties, single = True)
|
||||
return {
|
||||
'type': '%s_%s' % Scanner.file_types.get(type),
|
||||
'path': filepath,
|
||||
'part': fireEvent('scanner.partnumber', file, single = True),
|
||||
}
|
||||
|
||||
def deleteView(self, id = None, **kwargs):
|
||||
|
||||
@@ -171,60 +156,58 @@ class Release(Plugin):
|
||||
'success': self.delete(id)
|
||||
}
|
||||
|
||||
def delete(self, id):
|
||||
def delete(self, release_id):
|
||||
|
||||
try:
|
||||
db = get_session()
|
||||
db = get_db()
|
||||
|
||||
rel = db.query(Relea).filter_by(id = id).first()
|
||||
if rel:
|
||||
db.delete(rel)
|
||||
db.commit()
|
||||
return True
|
||||
rel = db.get('release', release_id, with_doc = True)
|
||||
db.delete(rel['doc'])
|
||||
return True
|
||||
except:
|
||||
log.error('Failed: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
return False
|
||||
|
||||
def clean(self, id):
|
||||
def clean(self, release_id):
|
||||
|
||||
try:
|
||||
db = get_session()
|
||||
db = get_db()
|
||||
|
||||
rel = db.query(Relea).filter_by(id = id).first()
|
||||
if rel:
|
||||
for release_file in rel.files:
|
||||
if not os.path.isfile(ss(release_file.path)):
|
||||
db.delete(release_file)
|
||||
db.commit()
|
||||
rel = db.get('release', release_id, with_doc = True)
|
||||
files = []
|
||||
for release_file in rel['files']:
|
||||
if os.path.isfile(ss(release_file['path'])):
|
||||
files.append(release_file)
|
||||
|
||||
if len(rel.files) == 0:
|
||||
self.delete(id)
|
||||
if len(rel['files']) == 0:
|
||||
self.delete(rel['_id'])
|
||||
else:
|
||||
rel['files'] = files
|
||||
db.update(rel)
|
||||
|
||||
return True
|
||||
return True
|
||||
except:
|
||||
log.error('Failed: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
return False
|
||||
|
||||
def ignore(self, id = None, **kwargs):
|
||||
def ignore(self, release_id = None, **kwargs):
|
||||
|
||||
db = get_session()
|
||||
db = get_db()
|
||||
|
||||
rel = db.query(Relea).filter_by(id = id).first()
|
||||
if rel:
|
||||
ignored_status, failed_status, available_status = fireEvent('status.get', ['ignored', 'failed', 'available'], single = True)
|
||||
self.updateStatus(id, available_status if rel.status_id in [ignored_status.get('id'), failed_status.get('id')] else ignored_status)
|
||||
try:
|
||||
rel = db.get('release', release_id, with_doc = True)['doc']
|
||||
self.updateStatus(release_id, 'available' if rel['status'] in ['ignored', 'failed'] else 'ignored')
|
||||
|
||||
return {
|
||||
'success': True
|
||||
}
|
||||
except:
|
||||
log.error('Failed: %s', traceback.format_exc())
|
||||
|
||||
db.close()
|
||||
return {
|
||||
'success': True
|
||||
'success': False
|
||||
}
|
||||
|
||||
def manualDownload(self, id = None, **kwargs):
|
||||
@@ -265,7 +248,7 @@ class Release(Plugin):
|
||||
if success:
|
||||
fireEvent('notify.frontend', type = 'release.manual_download', data = True, message = 'Successfully snatched "%s"' % item['name'])
|
||||
|
||||
db.close()
|
||||
pass #db.close()
|
||||
return {
|
||||
'success': success == True
|
||||
}
|
||||
@@ -361,7 +344,7 @@ class Release(Plugin):
|
||||
db.rollback()
|
||||
return False
|
||||
finally:
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
return True
|
||||
|
||||
@@ -441,7 +424,7 @@ class Release(Plugin):
|
||||
log.error('Failed: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
return []
|
||||
|
||||
@@ -458,7 +441,7 @@ class Release(Plugin):
|
||||
releases = [r.to_dict({'info': {}, 'files': {}}) for r in releases_raw]
|
||||
releases = sorted(releases, key = lambda k: k['info'].get('score', 0), reverse = True)
|
||||
|
||||
db.close()
|
||||
pass #db.close()
|
||||
return releases
|
||||
|
||||
def forMovieView(self, id = None, **kwargs):
|
||||
@@ -506,6 +489,6 @@ class Release(Plugin):
|
||||
log.error('Failed: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
return False
|
||||
@@ -598,7 +598,7 @@ class Renamer(Plugin):
|
||||
break
|
||||
|
||||
self.renaming_started = False
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
def getRenameExtras(self, extra_type = '', replacements = None, folder_name = '', file_name = '', destination = '', group = None, current_file = '', remove_multiple = False):
|
||||
if not group: group = {}
|
||||
@@ -1045,7 +1045,7 @@ Remove it if you want it to be renamed (again, or at least let it try again)
|
||||
self.checking_snatched = False
|
||||
return True
|
||||
finally:
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
def extendReleaseDownload(self, release_download):
|
||||
|
||||
@@ -1068,7 +1068,7 @@ Remove it if you want it to be renamed (again, or at least let it try again)
|
||||
if not rls:
|
||||
log.error('Download ID %s from downloader %s not found in releases', (release_download.get('id'), release_download.get('downloader')))
|
||||
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
if rls:
|
||||
|
||||
|
||||
@@ -441,7 +441,7 @@ class Scanner(Plugin):
|
||||
else:
|
||||
log.debug('Found no movies in the folder %s', folder)
|
||||
|
||||
db.close()
|
||||
pass #db.close()
|
||||
return processed_movies
|
||||
|
||||
def getMetaData(self, group, folder = '', release_download = None):
|
||||
@@ -609,7 +609,7 @@ class Scanner(Plugin):
|
||||
break
|
||||
except:
|
||||
pass
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
# Search based on identifiers
|
||||
if not imdb_id:
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
from .main import StatusPlugin
|
||||
|
||||
|
||||
def start():
|
||||
return StatusPlugin()
|
||||
|
||||
config = []
|
||||
@@ -1,137 +0,0 @@
|
||||
import traceback
|
||||
from couchpotato import get_session
|
||||
from couchpotato.api import addApiView
|
||||
from couchpotato.core.event import addEvent
|
||||
from couchpotato.core.helpers.encoding import toUnicode
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.plugins.base import Plugin
|
||||
from couchpotato.core.settings.model import Status
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class StatusPlugin(Plugin):
|
||||
|
||||
statuses = {
|
||||
'needs_update': 'Needs update',
|
||||
'active': 'Active',
|
||||
'done': 'Done',
|
||||
'downloaded': 'Downloaded',
|
||||
'wanted': 'Wanted',
|
||||
'snatched': 'Snatched',
|
||||
'failed': 'Failed',
|
||||
'deleted': 'Deleted',
|
||||
'ignored': 'Ignored',
|
||||
'available': 'Available',
|
||||
'suggest': 'Suggest',
|
||||
'seeding': 'Seeding',
|
||||
'missing': 'Missing',
|
||||
}
|
||||
status_cached = {}
|
||||
|
||||
def __init__(self):
|
||||
addEvent('status.get', self.get)
|
||||
addEvent('status.get_by_id', self.getById)
|
||||
addEvent('status.all', self.all)
|
||||
addEvent('app.initialize', self.fill)
|
||||
addEvent('app.load', self.all) # Cache all statuses
|
||||
|
||||
addApiView('status.list', self.list, docs = {
|
||||
'desc': 'Check for available update',
|
||||
'return': {'type': 'object', 'example': """{
|
||||
'success': True,
|
||||
'list': array, statuses
|
||||
}"""}
|
||||
})
|
||||
|
||||
def list(self, **kwargs):
|
||||
|
||||
return {
|
||||
'success': True,
|
||||
'list': self.all()
|
||||
}
|
||||
|
||||
def getById(self, id):
|
||||
db = get_session()
|
||||
status = db.query(Status).filter_by(id = id).first()
|
||||
status_dict = status.to_dict()
|
||||
db.close()
|
||||
|
||||
return status_dict
|
||||
|
||||
def all(self):
|
||||
|
||||
db = get_session()
|
||||
|
||||
statuses = db.query(Status).all()
|
||||
|
||||
temp = []
|
||||
for status in statuses:
|
||||
s = status.to_dict()
|
||||
temp.append(s)
|
||||
|
||||
# Update cache
|
||||
self.status_cached[status.identifier] = s
|
||||
|
||||
db.close()
|
||||
return temp
|
||||
|
||||
def get(self, identifiers):
|
||||
|
||||
if not isinstance(identifiers, list):
|
||||
identifiers = [identifiers]
|
||||
|
||||
try:
|
||||
db = get_session()
|
||||
return_list = []
|
||||
|
||||
for identifier in identifiers:
|
||||
|
||||
if self.status_cached.get(identifier):
|
||||
return_list.append(self.status_cached.get(identifier))
|
||||
continue
|
||||
|
||||
s = db.query(Status).filter_by(identifier = identifier).first()
|
||||
if not s:
|
||||
s = Status(
|
||||
identifier = identifier,
|
||||
label = toUnicode(identifier.capitalize())
|
||||
)
|
||||
db.add(s)
|
||||
db.commit()
|
||||
|
||||
status_dict = s.to_dict()
|
||||
|
||||
self.status_cached[identifier] = status_dict
|
||||
return_list.append(status_dict)
|
||||
|
||||
return return_list if len(identifiers) > 1 else return_list[0]
|
||||
except:
|
||||
log.error('Failed: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
def fill(self):
|
||||
|
||||
try:
|
||||
db = get_session()
|
||||
|
||||
for identifier, label in self.statuses.items():
|
||||
s = db.query(Status).filter_by(identifier = identifier).first()
|
||||
if not s:
|
||||
log.info('Creating status: %s', label)
|
||||
s = Status(
|
||||
identifier = identifier,
|
||||
label = toUnicode(label)
|
||||
)
|
||||
db.add(s)
|
||||
|
||||
s.label = toUnicode(label)
|
||||
db.commit()
|
||||
except:
|
||||
log.error('Failed: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
var StatusBase = new Class({
|
||||
|
||||
setup: function(statuses){
|
||||
var self = this;
|
||||
|
||||
self.statuses = statuses;
|
||||
|
||||
},
|
||||
|
||||
get: function(id){
|
||||
return this.statuses.filter(function(status){
|
||||
return status.id == id
|
||||
}).pick()
|
||||
},
|
||||
|
||||
});
|
||||
window.Status = new StatusBase();
|
||||
@@ -41,7 +41,7 @@ class Subtitle(Plugin):
|
||||
# get subtitles for those files
|
||||
subliminal.list_subtitles(files, cache_dir = Env.get('cache_dir'), multi = True, languages = self.getLanguages(), services = self.services)
|
||||
|
||||
db.close()
|
||||
pass #db.close()
|
||||
|
||||
def searchSingle(self, group):
|
||||
if self.isDisabled(): return
|
||||
|
||||
@@ -104,7 +104,7 @@ class MovieResultModifier(Plugin):
|
||||
except:
|
||||
log.error('Tried getting more info on searched movies: %s', traceback.format_exc())
|
||||
|
||||
db.close()
|
||||
pass #db.close()
|
||||
return temp
|
||||
|
||||
def checkLibrary(self, result):
|
||||
|
||||
@@ -90,6 +90,7 @@ class MetaDataBase(Plugin):
|
||||
file_type = {}
|
||||
|
||||
for ft in file_types:
|
||||
# TODO: change type to "image_"+wanted_file_type
|
||||
if ft.get('identifier') == wanted_file_type:
|
||||
file_type = ft
|
||||
break
|
||||
|
||||
@@ -4,6 +4,7 @@ from couchpotato.api import addApiView
|
||||
from couchpotato.core.event import addEvent, fireEvent
|
||||
from couchpotato.core.helpers.encoding import toUnicode
|
||||
from couchpotato.core.helpers.variable import mergeDicts, tryInt, tryFloat
|
||||
from couchpotato.core.settings.index import PropertyIndex
|
||||
from couchpotato.core.settings.model import Properties
|
||||
import ConfigParser
|
||||
|
||||
@@ -42,6 +43,7 @@ class Settings(object):
|
||||
}
|
||||
}"""}
|
||||
})
|
||||
|
||||
addApiView('settings.save', self.saveView, docs = {
|
||||
'desc': 'Save setting to config file (settings.conf)',
|
||||
'params': {
|
||||
@@ -51,6 +53,8 @@ class Settings(object):
|
||||
}
|
||||
})
|
||||
|
||||
addEvent('database.setup', self.databaseSetup)
|
||||
|
||||
def setFile(self, config_file):
|
||||
self.file = config_file
|
||||
|
||||
@@ -62,6 +66,17 @@ class Settings(object):
|
||||
|
||||
self.connectEvents()
|
||||
|
||||
def databaseSetup(self):
|
||||
from couchpotato import get_db
|
||||
|
||||
db = get_db()
|
||||
|
||||
try:
|
||||
db.add_index(PropertyIndex(db.path, 'property'))
|
||||
except:
|
||||
self.log.debug('Index already exists')
|
||||
db.edit_index(PropertyIndex(db.path, 'property'))
|
||||
|
||||
def parser(self):
|
||||
return self.p
|
||||
|
||||
@@ -206,36 +221,33 @@ class Settings(object):
|
||||
}
|
||||
|
||||
def getProperty(self, identifier):
|
||||
from couchpotato import get_session
|
||||
from couchpotato import get_db
|
||||
|
||||
db = get_session()
|
||||
db = get_db()
|
||||
prop = None
|
||||
try:
|
||||
propert = db.query(Properties).filter_by(identifier = identifier).first()
|
||||
prop = propert.value
|
||||
propert = db.get('property', identifier, with_doc = True)
|
||||
prop = propert['doc']['value']
|
||||
except:
|
||||
pass
|
||||
self.log.debug('Property doesn\'t exist: %s', traceback.format_exc(0))
|
||||
|
||||
db.close()
|
||||
return prop
|
||||
|
||||
def setProperty(self, identifier, value = ''):
|
||||
from couchpotato import get_session
|
||||
from couchpotato import get_db
|
||||
|
||||
db = get_db()
|
||||
|
||||
try:
|
||||
db = get_session()
|
||||
|
||||
p = db.query(Properties).filter_by(identifier = identifier).first()
|
||||
if not p:
|
||||
p = Properties()
|
||||
db.add(p)
|
||||
|
||||
p.identifier = identifier
|
||||
p.value = toUnicode(value)
|
||||
|
||||
db.commit()
|
||||
p = db.get('property', identifier, with_doc = True)
|
||||
p['doc'].update({
|
||||
'identifier': identifier,
|
||||
'value': toUnicode(value),
|
||||
})
|
||||
db.update(p['doc'])
|
||||
except:
|
||||
self.log.error('Failed: %s', traceback.format_exc())
|
||||
db.rollback()
|
||||
finally:
|
||||
db.close()
|
||||
db.insert({
|
||||
'type': 'property',
|
||||
'identifier': identifier,
|
||||
'value': toUnicode(value),
|
||||
})
|
||||
@@ -0,0 +1,16 @@
|
||||
from CodernityDB.hash_index import UniqueHashIndex, HashIndex
|
||||
from hashlib import md5
|
||||
|
||||
|
||||
class PropertyIndex(HashIndex):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['key_format'] = '16s'
|
||||
super(PropertyIndex, self).__init__(*args, **kwargs)
|
||||
|
||||
def make_key(self, key):
|
||||
return md5(key).digest()
|
||||
|
||||
def make_key_value(self, data):
|
||||
if data.get('type') == 'property':
|
||||
return md5(data['identifier']).digest(), None
|
||||
Reference in new issue
Block a user