Browse Source

Merge branch 'refs/heads/develop'

pull/228/head
Ruud 13 years ago
parent
commit
89315cb291
  1. 2
      couchpotato/core/_base/updater/main.py
  2. 2
      couchpotato/core/helpers/encoding.py
  3. 8
      couchpotato/core/helpers/request.py
  4. 12
      couchpotato/core/plugins/base.py
  5. 1
      couchpotato/core/plugins/library/main.py
  6. 43
      couchpotato/core/plugins/movie/main.py
  7. 2
      couchpotato/core/plugins/movie/static/movie.css
  8. 4
      couchpotato/core/providers/movie/imdbapi/main.py
  9. 2
      couchpotato/core/providers/nzb/mysterbin/main.py
  10. 4
      couchpotato/core/providers/nzb/newznab/__init__.py
  11. 8
      couchpotato/core/providers/nzb/nzbclub/main.py
  12. 9
      couchpotato/core/providers/nzb/nzbindex/main.py
  13. 2
      couchpotato/core/providers/nzb/nzbmatrix/main.py
  14. 33
      couchpotato/core/providers/nzb/nzbs/__init__.py
  15. 96
      couchpotato/core/providers/nzb/nzbs/main.py
  16. 2
      couchpotato/static/scripts/page/wanted.js

2
couchpotato/core/_base/updater/main.py

@ -56,7 +56,7 @@ class Updater(Plugin):
fireEventAsync('app.crappy_restart') fireEventAsync('app.crappy_restart')
else: else:
if self.conf('notification'): 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): def info(self):
return self.updater.info() return self.updater.info()

2
couchpotato/core/helpers/encoding.py

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

8
couchpotato/core/helpers/request.py

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

12
couchpotato/core/plugins/base.py

@ -198,7 +198,7 @@ class Plugin(object):
log.error("Something went wrong when finishing the plugin function. Could not find the 'is_running' key") 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) cache = Env.get('cache').get(cache_key)
if cache: if cache:
if not Env.get('dev'): log.debug('Getting cache %s' % cache_key) if not Env.get('dev'): log.debug('Getting cache %s' % cache_key)
@ -206,8 +206,14 @@ class Plugin(object):
if url: if url:
try: 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 return data
except: except:
pass pass

1
couchpotato/core/plugins/library/main.py

@ -68,6 +68,7 @@ class LibraryPlugin(Plugin):
do_update = False do_update = False
else: else:
info = fireEvent('movie.info', merge = True, identifier = identifier) 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: if not info or len(info) == 0:
log.error('Could not update, no movie info to work with: %s' % identifier) log.error('Could not update, no movie info to work with: %s' % identifier)
return False return False

43
couchpotato/core/plugins/movie/main.py

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

2
couchpotato/core/plugins/movie/static/movie.css

@ -288,7 +288,7 @@
text-align: left; text-align: left;
padding: 0 10px; 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 .type { width: 130px; }
.movies .options .table .is_available { width: 90px; } .movies .options .table .is_available { width: 90px; }
.movies .options .table .age, .movies .options .table .age,

4
couchpotato/core/providers/movie/imdbapi/main.py

@ -31,7 +31,7 @@ class IMDBAPI(MovieProvider):
return [] return []
cache_key = 'imdbapi.cache.%s' % q 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: if cached:
result = self.parseMovie(cached) result = self.parseMovie(cached)
@ -49,7 +49,7 @@ class IMDBAPI(MovieProvider):
return {} return {}
cache_key = 'imdbapi.cache.%s' % identifier 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: if cached:
result = self.parseMovie(cached) result = self.parseMovie(cached)

2
couchpotato/core/providers/nzb/mysterbin/main.py

@ -67,7 +67,7 @@ class Mysterbin(NZBProvider):
description = '' description = ''
if result.find('a', text = 'View NFO'): 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 = { new = {
'id': myster_id, 'id': myster_id,

4
couchpotato/core/providers/nzb/newznab/__init__.py

@ -10,7 +10,7 @@ config = [{
'tab': 'searcher', 'tab': 'searcher',
'subtab': 'providers', 'subtab': 'providers',
'name': 'newznab', '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, 'wizard': True,
'options': [ 'options': [
{ {
@ -23,7 +23,7 @@ config = [{
}, },
{ {
'name': 'host', 'name': 'host',
'default': 'nzb.su,dognzb.cr,beta.nzbs.org', 'default': 'nzb.su,dognzb.cr,nzbs.org',
'description': 'The hostname of your newznab provider', 'description': 'The hostname of your newznab provider',
}, },
{ {

8
couchpotato/core/providers/nzb/nzbclub/main.py

@ -1,3 +1,4 @@
from BeautifulSoup import BeautifulSoup
from couchpotato.core.event import fireEvent from couchpotato.core.event import fireEvent
from couchpotato.core.helpers.encoding import toUnicode, tryUrlencode from couchpotato.core.helpers.encoding import toUnicode, tryUrlencode
from couchpotato.core.helpers.rss import RSS from couchpotato.core.helpers.rss import RSS
@ -57,7 +58,10 @@ class NZBClub(NZBProvider, RSS):
size = enclosure['length'] size = enclosure['length']
date = self.getTextElement(nzb, "pubDate") 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 = { new = {
'id': nzbclub_id, 'id': nzbclub_id,
@ -73,7 +77,7 @@ class NZBClub(NZBProvider, RSS):
} }
new['score'] = fireEvent('score.calculate', new, movie, single = True) 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']) log.info('Wrong: Seems to be passworded files: %s' % new['name'])
continue continue

9
couchpotato/core/providers/nzb/nzbindex/main.py

@ -1,3 +1,4 @@
from BeautifulSoup import BeautifulSoup
from couchpotato.core.event import fireEvent from couchpotato.core.event import fireEvent
from couchpotato.core.helpers.encoding import toUnicode, tryUrlencode from couchpotato.core.helpers.encoding import toUnicode, tryUrlencode
from couchpotato.core.helpers.rss import RSS from couchpotato.core.helpers.rss import RSS
@ -62,9 +63,11 @@ class NzbIndex(NZBProvider, RSS):
try: try:
description = self.getTextElement(nzb, "description") description = self.getTextElement(nzb, "description")
if ' nfo' in description.lower(): if '/nfo/' in description.lower():
nfo_url = re.search('href="(?P<nfo>.+)"', description).group('nfo') nfo_url = re.search('href=\"(?P<nfo>.+)\" ', description).group('nfo')
description = toUnicode(self.getCache('nzbindex.%s' % nzbindex_id, nfo_url, timeout = 25920000)) 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: except:
pass pass

2
couchpotato/core/providers/nzb/nzbmatrix/main.py

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

33
couchpotato/core/providers/nzb/nzbs/__init__.py

@ -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="'
},
],
},
],
}]

96
couchpotato/core/providers/nzb/nzbs/main.py

@ -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'))

2
couchpotato/static/scripts/page/wanted.js

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

Loading…
Cancel
Save