Try NoSQL

This commit is contained in:
Ruud committed 2014-01-29 17:49:54 +01:00
1 parent aab10fb599
commit a254886bad
65 files changed
+7372 -761

No files matched your search

+2 -2
View File
@@ -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)
+1 -1
View File
@@ -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()
+1 -1
View File
@@ -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)
+2 -2
View File
@@ -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):
+14 -14
View File
@@ -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()
+49 -26
View File
@@ -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()
+1 -1
View File
@@ -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)
+59 -67
View File
@@ -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 {}
+35 -55
View File
@@ -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
+48 -60
View File
@@ -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,
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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)
+8 -8
View File
@@ -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()
+1 -1
View File
@@ -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):
+1 -1
View File
@@ -119,7 +119,7 @@ class Dashboard(Plugin):
'files': {},
}))
db.close()
pass #db.close()
return {
'success': True,
'empty': len(movies) == 0,
+1 -107
View File
@@ -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()
}
+1 -1
View File
@@ -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 = []
+20
View File
@@ -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']
+72
View File
@@ -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')
+19 -29
View File
@@ -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
+4 -4
View File
@@ -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
+58 -75
View File
@@ -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
+3 -3
View File
@@ -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:
+2 -2
View File
@@ -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 = []
-137
View File
@@ -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();
+1 -1
View File
@@ -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
+34 -22
View File
@@ -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),
})
+16
View File
@@ -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