Merge branch 'refs/heads/develop'

This commit is contained in:
Ruud
2012-05-04 17:27:12 +02:00
16 changed files with 68 additions and 162 deletions

View File

@@ -56,7 +56,7 @@ class Updater(Plugin):
fireEventAsync('app.crappy_restart')
else:
if self.conf('notification'):
fireEvent('updater.available', message = 'A new update is available', data = self.updater.getVersion())
fireEvent('updater.available', message = 'A new update is available', data = self.updater.info())
def info(self):
return self.updater.info()

View File

@@ -15,7 +15,7 @@ def toSafeString(original):
def simplifyString(original):
string = stripAccents(original.lower())
string = toSafeString(' '.join(re.split('\W+', string)))
split = re.split('\W+', string.lower())
split = re.split('\W+|_', string.lower())
return toUnicode(' '.join(split))
def toUnicode(original, *args):

View File

@@ -3,7 +3,7 @@ from couchpotato.core.helpers.variable import natcmp
from flask.globals import current_app
from flask.helpers import json
from libs.werkzeug.urls import url_decode
from urllib import unquote_plus
from urllib import unquote
import flask
import re
@@ -26,7 +26,7 @@ def getParams():
for item in nested:
if item is nested[-1]:
current[item] = toUnicode(unquote_plus(value)).encode('utf-8')
current[item] = toUnicode(unquote(value)).encode('utf-8')
else:
try:
current[item]
@@ -35,7 +35,7 @@ def getParams():
current = current[item]
else:
temp[param] = toUnicode(unquote_plus(value)).encode('utf-8')
temp[param] = toUnicode(unquote(value)).encode('utf-8')
return dictToList(temp)
@@ -57,7 +57,7 @@ def dictToList(params):
def getParam(attr, default = None):
try:
return toUnicode(unquote_plus(getattr(flask.request, 'args').get(attr, default))).encode('utf-8')
return toUnicode(unquote(getattr(flask.request, 'args').get(attr, default))).encode('utf-8')
except:
return default

View File

@@ -198,7 +198,7 @@ class Plugin(object):
log.error("Something went wrong when finishing the plugin function. Could not find the 'is_running' key")
def getCache(self, cache_key, url = None, timeout = 300, url_timeout = 10):
def getCache(self, cache_key, url = None, **kwargs):
cache = Env.get('cache').get(cache_key)
if cache:
if not Env.get('dev'): log.debug('Getting cache %s' % cache_key)
@@ -206,8 +206,14 @@ class Plugin(object):
if url:
try:
data = self.urlopen(url, timeout = url_timeout)
self.setCache(cache_key, data, timeout = timeout)
cache_timeout = 300
if kwargs.get('cache_timeout'):
cache_timeout = kwargs.get('cache_timeout')
del kwargs['cache_timeout']
data = self.urlopen(url, **kwargs)
self.setCache(cache_key, data, timeout = cache_timeout)
return data
except:
pass

View File

@@ -68,6 +68,7 @@ class LibraryPlugin(Plugin):
do_update = False
else:
info = fireEvent('movie.info', merge = True, identifier = identifier)
del info['in_wanted'], info['in_library'] # Don't need those here
if not info or len(info) == 0:
log.error('Could not update, no movie info to work with: %s' % identifier)
return False

View File

@@ -51,6 +51,12 @@ class MoviePlugin(Plugin):
'movies': array, movies found,
}"""}
})
addApiView('movie.get', self.getView, docs = {
'desc': 'Get a movie by id',
'params': {
'id': {'desc': 'The id of the movie'},
}
})
addApiView('movie.refresh', self.refresh, docs = {
'desc': 'Refresh a movie by id',
'params': {
@@ -88,12 +94,25 @@ class MoviePlugin(Plugin):
addEvent('movie.list', self.list)
addEvent('movie.restatus', self.restatus)
def getView(self):
movie_id = getParam('id')
movie = self.get(movie_id) if movie_id else None
return jsonified({
'success': movie is not None,
'movie': movie,
})
def get(self, movie_id):
db = get_session()
m = db.query(Movie).filter_by(id = movie_id).first()
return m.to_dict(self.default_dict)
if m:
return m.to_dict(self.default_dict)
return None
def list(self, status = ['active'], limit_offset = None, starts_with = None, search = None):
@@ -169,11 +188,9 @@ class MoviePlugin(Plugin):
status = [status]
q = db.query(Movie) \
.join(Movie.library, Library.titles) \
.join(Movie.library, Library.titles, Movie.status) \
.options(joinedload_all('library.titles')) \
.filter(LibraryTitle.default == True) \
.filter(or_(*[Movie.status.has(identifier = s) for s in status])) \
.group_by(Movie.id)
.filter(or_(*[Movie.status.has(identifier = s) for s in status]))
results = q.all()
@@ -380,13 +397,15 @@ class MoviePlugin(Plugin):
total_deleted = 0
new_movie_status = None
for release in movie.releases:
if delete_from == 'wanted' and release.status_id != done_status.get('id'):
db.delete(release)
total_deleted += 1
if delete_from == 'wanted':
if release.status_id != done_status.get('id'):
db.delete(release)
total_deleted += 1
new_movie_status = 'done'
elif delete_from == 'manage' and release.status_id == done_status.get('id'):
db.delete(release)
total_deleted += 1
elif delete_from == 'manage':
if release.status_id == done_status.get('id'):
db.delete(release)
total_deleted += 1
new_movie_status = 'active'
db.commit()
@@ -397,6 +416,8 @@ class MoviePlugin(Plugin):
new_status = fireEvent('status.get', new_movie_status, single = True)
movie.status_id = new_status.get('id')
db.commit()
else:
fireEvent('movie.restatus', movie.id, single = True)
return True

View File

@@ -288,7 +288,7 @@
text-align: left;
padding: 0 10px;
}
.movies .options .table.files .name { width: 605px; }
.movies .options .table.files .name { width: 590px; }
.movies .options .table .type { width: 130px; }
.movies .options .table .is_available { width: 90px; }
.movies .options .table .age,

View File

@@ -31,7 +31,7 @@ class IMDBAPI(MovieProvider):
return []
cache_key = 'imdbapi.cache.%s' % q
cached = self.getCache(cache_key, self.urls['search'] % tryUrlencode({'t': name_year.get('name'), 'y': name_year.get('year', '')}), url_timeout = 3)
cached = self.getCache(cache_key, self.urls['search'] % tryUrlencode({'t': name_year.get('name'), 'y': name_year.get('year', '')}), timeout = 3)
if cached:
result = self.parseMovie(cached)
@@ -49,7 +49,7 @@ class IMDBAPI(MovieProvider):
return {}
cache_key = 'imdbapi.cache.%s' % identifier
cached = self.getCache(cache_key, self.urls['info'] % identifier, url_timeout = 3)
cached = self.getCache(cache_key, self.urls['info'] % identifier, timeout = 3)
if cached:
result = self.parseMovie(cached)

View File

@@ -67,7 +67,7 @@ class Mysterbin(NZBProvider):
description = ''
if result.find('a', text = 'View NFO'):
description = toUnicode(self.getCache('mysterbin.%s' % myster_id, self.urls['nfo'] % myster_id, timeout = 25920000))
description = toUnicode(self.getCache('mysterbin.%s' % myster_id, self.urls['nfo'] % myster_id, cache_timeout = 25920000))
new = {
'id': myster_id,

View File

@@ -10,7 +10,7 @@ config = [{
'tab': 'searcher',
'subtab': 'providers',
'name': 'newznab',
'description': 'Enable multiple NewzNab providers such as <a href="http://nzb.su" target="_blank">NZB.su</a>',
'description': 'Enable multiple NewzNab providers such as <a href="http://nzb.su" target="_blank">NZB.su</a> and <a href="http://nzbs.org" target="_blank">nzbs.org</a>',
'wizard': True,
'options': [
{
@@ -23,7 +23,7 @@ config = [{
},
{
'name': 'host',
'default': 'nzb.su,dognzb.cr,beta.nzbs.org',
'default': 'nzb.su,dognzb.cr,nzbs.org',
'description': 'The hostname of your newznab provider',
},
{

View File

@@ -1,3 +1,4 @@
from BeautifulSoup import BeautifulSoup
from couchpotato.core.event import fireEvent
from couchpotato.core.helpers.encoding import toUnicode, tryUrlencode
from couchpotato.core.helpers.rss import RSS
@@ -57,7 +58,10 @@ class NZBClub(NZBProvider, RSS):
size = enclosure['length']
date = self.getTextElement(nzb, "pubDate")
description = toUnicode(self.getCache('nzbclub.%s' % nzbclub_id, self.getTextElement(nzb, "link"), timeout = 25920000))
full_description = self.getCache('nzbclub.%s' % nzbclub_id, self.getTextElement(nzb, "link"), cache_timeout = 25920000)
html = BeautifulSoup(full_description)
nfo_pre = html.find('pre', attrs = {'class':'nfo'})
description = toUnicode(nfo_pre.text) if nfo_pre else ''
new = {
'id': nzbclub_id,
@@ -73,7 +77,7 @@ class NZBClub(NZBProvider, RSS):
}
new['score'] = fireEvent('score.calculate', new, movie, single = True)
if 'ARCHIVE inside ARCHIVE' in description:
if 'ARCHIVE inside ARCHIVE' in full_description:
log.info('Wrong: Seems to be passworded files: %s' % new['name'])
continue

View File

@@ -1,3 +1,4 @@
from BeautifulSoup import BeautifulSoup
from couchpotato.core.event import fireEvent
from couchpotato.core.helpers.encoding import toUnicode, tryUrlencode
from couchpotato.core.helpers.rss import RSS
@@ -62,9 +63,11 @@ class NzbIndex(NZBProvider, RSS):
try:
description = self.getTextElement(nzb, "description")
if ' nfo' in description.lower():
nfo_url = re.search('href="(?P<nfo>.+)"', description).group('nfo')
description = toUnicode(self.getCache('nzbindex.%s' % nzbindex_id, nfo_url, timeout = 25920000))
if '/nfo/' in description.lower():
nfo_url = re.search('href=\"(?P<nfo>.+)\" ', description).group('nfo')
full_description = self.getCache('nzbindex.%s' % nzbindex_id, url = nfo_url, cache_timeout = 25920000)
html = BeautifulSoup(full_description)
description = toUnicode(html.find('pre', attrs = {'id':'nfo0'}).text)
except:
pass

View File

@@ -51,7 +51,7 @@ class NZBMatrix(NZBProvider, RSS):
cache_key = 'nzbmatrix.%s.%s' % (movie['library'].get('identifier'), cat_ids)
single_cat = True
data = self.getCache(cache_key, url)
data = self.getCache(cache_key, url, cache_timeout = 1800, headers = {'User-Agent': 'CouchPotato'})
if data:
try:
try:

View File

@@ -1,33 +0,0 @@
from .main import Nzbs
def start():
return Nzbs()
config = [{
'name': 'nzbs',
'groups': [
{
'tab': 'searcher',
'subtab': 'providers',
'name': 'nzbs',
'description': 'Id and Key can be found <a href="http://nzbs.org/index.php?action=rss" target="_blank">on your nzbs.org RSS page</a>.',
'wizard': True,
'options': [
{
'name': 'enabled',
'type': 'enabler',
},
{
'name': 'id',
'label': 'Id',
'description': 'The number after "&amp;i="',
},
{
'name': 'api_key',
'label': 'Api Key',
'description': 'The string after "&amp;h="'
},
],
},
],
}]

View File

@@ -1,96 +0,0 @@
from couchpotato.core.event import fireEvent
from couchpotato.core.helpers.encoding import simplifyString, tryUrlencode
from couchpotato.core.helpers.rss import RSS
from couchpotato.core.logger import CPLog
from couchpotato.core.providers.nzb.base import NZBProvider
from dateutil.parser import parse
import time
import xml.etree.ElementTree as XMLTree
log = CPLog(__name__)
class Nzbs(NZBProvider, RSS):
urls = {
'download': 'https://nzbs.org/index.php?action=getnzb&nzbid=%s%s',
'nfo': 'https://nzbs.org/index.php?action=view&nzbid=%s&nfo=1',
'detail': 'https://nzbs.org/index.php?action=view&nzbid=%s',
'api': 'https://nzbs.org/rss.php',
}
cat_ids = [
([4], ['720p', '1080p']),
([2], ['cam', 'ts', 'dvdrip', 'tc', 'brrip', 'r5', 'scr']),
([9], ['dvdr']),
]
cat_backup_id = 't2'
http_time_between_calls = 3 # Seconds
def search(self, movie, quality):
results = []
if self.isDisabled() or not self.isAvailable(self.urls['api'] + '?test' + self.getApiExt()):
return results
cat_id = self.getCatId(quality.get('identifier'))
arguments = tryUrlencode({
'action':'search',
'q': simplifyString(movie['library']['titles'][0]['title']),
'catid': cat_id[0],
'i': self.conf('id'),
'h': self.conf('api_key'),
})
url = "%s?%s" % (self.urls['api'], arguments)
cache_key = 'nzbs.%s.%s' % (movie['library'].get('identifier'), str(cat_id))
data = self.getCache(cache_key, url)
if data:
try:
try:
data = XMLTree.fromstring(data)
nzbs = self.getElements(data, 'channel/item')
except Exception, e:
log.debug('%s, %s' % (self.getName(), e))
return results
for nzb in nzbs:
id = int(self.getTextElement(nzb, "link").partition('nzbid=')[2])
new = {
'id': id,
'type': 'nzb',
'provider': self.getName(),
'name': self.getTextElement(nzb, "title"),
'age': self.calculateAge(int(time.mktime(parse(self.getTextElement(nzb, "pubDate")).timetuple()))),
'size': self.parseSize(self.getTextElement(nzb, "description").split('</a><br />')[1].split('">')[1]),
'url': self.urls['download'] % (id, self.getApiExt()),
'download': self.download,
'detail_url': self.urls['detail'] % id,
'description': self.getTextElement(nzb, "description"),
'check_nzb': True,
}
new['score'] = fireEvent('score.calculate', new, movie, single = True)
is_correct_movie = fireEvent('searcher.correct_movie',
nzb = new, movie = movie, quality = quality,
imdb_results = False, single_category = False, single = True)
if is_correct_movie:
results.append(new)
self.found(new)
return results
except SyntaxError:
log.error('Failed to parse XML response from NZBMatrix.com')
return results
def isEnabled(self):
return NZBProvider.isEnabled(self) and self.conf('enabled') and self.conf('id') and self.conf('api_key')
def getApiExt(self):
return '&i=%s&h=%s' % (self.conf('id'), self.conf('api_key'))

View File

@@ -243,7 +243,7 @@ window.addEvent('domready', function(){
create: function(){
var self = this;
self.el = new Element('a.files', {
self.el = new Element('a.directory', {
'title': 'Available files',
'events': {
'click': self.showFiles.bind(self)