Merge branch 'refs/heads/develop'

This commit is contained in:
Ruud
2012-12-01 11:48:54 +01:00
26 changed files with 314 additions and 412 deletions
+1 -1
View File
@@ -28,7 +28,7 @@ class Sabnzbd(Downloader):
if filedata:
if len(filedata) < 50:
log.error('No proper nzb available!')
log.error('No proper nzb available: %s', (filedata))
return False
# If it's a .rar, it adds the .rar extension, otherwise it stays .nzb
@@ -0,0 +1,44 @@
from .main import Synology
def start():
return Synology()
config = [{
'name': 'synology',
'groups': [
{
'tab': 'downloaders',
'name': 'synology',
'label': 'Synology',
'description': 'Send torrents to Synology\'s Download Station.',
'wizard': True,
'options': [
{
'name': 'enabled',
'default': 0,
'type': 'enabler',
'radio_group': 'torrent',
},
{
'name': 'host',
'default': 'localhost:5000',
'description': 'Hostname with port. Usually <strong>localhost:5000</strong>',
},
{
'name': 'username',
},
{
'name': 'password',
'type': 'password',
},
{
'name': 'manual',
'default': 0,
'type': 'bool',
'advanced': True,
'description': 'Disable this downloader for automated searches, but use it when I manually send a release.',
},
],
}
],
}]
@@ -0,0 +1,108 @@
from couchpotato.core.downloaders.base import Downloader
from couchpotato.core.helpers.encoding import isInt
from couchpotato.core.logger import CPLog
import httplib
import json
import urllib
import urllib2
log = CPLog(__name__)
class Synology(Downloader):
type = ['torrent_magnet']
log = CPLog(__name__)
def download(self, data, movie, manual = False, filedata = None):
if self.isDisabled(manual) or not self.isCorrectType(data.get('type')):
return
log.error('Sending "%s" (%s) to Synology.', (data.get('name'), data.get('type')))
# Load host from config and split out port.
host = self.conf('host').split(':')
if not isInt(host[1]):
log.error('Config properties are not filled in correctly, port is missing.')
return False
if data.get('type') == 'torrent':
log.error('Can\'t add binary torrent file')
return False
try:
# Send request to Transmission
srpc = SynologyRPC(host[0], host[1], self.conf('username'), self.conf('password'))
remote_torrent = srpc.add_torrent_uri(data.get('url'))
log.info('Response: %s', remote_torrent)
return remote_torrent['success']
except Exception, err:
log.error('Exception while adding torrent: %s', err)
return False
class SynologyRPC(object):
'''SynologyRPC lite library'''
def __init__(self, host = 'localhost', port = 5000, username = None, password = None):
super(SynologyRPC, self).__init__()
self.download_url = 'http://%s:%s/webapi/DownloadStation/task.cgi' % (host, port)
self.auth_url = 'http://%s:%s/webapi/auth.cgi' % (host, port)
self.username = username
self.password = password
self.session_name = 'DownloadStation'
def _login(self):
if self.username and self.password:
args = {'api': 'SYNO.API.Auth', 'account': self.username, 'passwd': self.password, 'version': 2,
'method': 'login', 'session': self.session_name, 'format': 'sid'}
response = self._req(self.auth_url, args)
if response['success'] == True:
self.sid = response['data']['sid']
log.debug('Sid=%s', self.sid)
return response
elif self.username or self.password:
log.error('User or password missing, not using authentication.')
return False
def _logout(self):
args = {'api':'SYNO.API.Auth', 'version':1, 'method':'logout', 'session':self.session_name, '_sid':self.sid}
return self._req(self.auth_url, args)
def _req(self, url, args):
req_url = url + '?' + urllib.urlencode(args)
try:
req_open = urllib2.urlopen(req_url)
response = json.loads(req_open.read())
if response['success'] == True:
log.info('Synology action successfull')
return response
except httplib.InvalidURL, err:
log.error('Invalid Transmission host, check your config %s', err)
return False
except urllib2.HTTPError, err:
log.error('SynologyRPC HTTPError: %s', err)
return False
except urllib2.URLError, err:
log.error('Unable to connect to Synology %s', err)
return False
def add_torrent_uri(self, torrent):
log.info('Adding torrent URL %s', torrent)
response = {}
# login
login = self._login()
if len(login) > 0 and login['success'] == True:
log.info('Login success, adding torrent')
args = {'api':'SYNO.DownloadStation.Task', 'version':1, 'method':'create', 'uri':torrent, '_sid':self.sid}
response = self._req(self.download_url, args)
self._logout()
else:
log.error('Couldn\'t login to Synology, %s', login)
return response
+2 -1
View File
@@ -56,7 +56,8 @@ class CPLog(object):
if not Env.get('dev'):
for replace in self.replace_private:
msg = re.sub('(%s=)[^\&]+' % replace, '%s=xxx' % replace, msg)
msg = re.sub('(\?%s=)[^\&]+' % replace, '?%s=xxx' % replace, msg)
msg = re.sub('(&%s=)[^\&]+' % replace, '&%s=xxx' % replace, msg)
# Replace api key
try:
+26 -23
View File
@@ -479,29 +479,32 @@ var ReleaseAction = new Class({
self.release_container.getElement('#release_'+self.next_release.id).addClass('next_release');
}
self.trynext_container.adopt(
new Element('span.or', {
'text': 'This movie is snatched, if anything went wrong, download'
}),
self.last_release ? new Element('a.button.orange', {
'text': 'the same release again',
'events': {
'click': self.trySameRelease.bind(self)
}
}) : null,
self.next_release && self.last_release ? new Element('span.or', {
'text': ','
}) : null,
self.next_release ? [new Element('a.button.green', {
'text': self.last_release ? 'another release' : 'the best release',
'events': {
'click': self.tryNextRelease.bind(self)
}
}),
new Element('span.or', {
'text': 'or pick one below'
})] : null
)
if(self.next_release || self.last_release){
self.trynext_container.adopt(
new Element('span.or', {
'text': 'This movie is snatched, if anything went wrong, download'
}),
self.last_release ? new Element('a.button.orange', {
'text': 'the same release again',
'events': {
'click': self.trySameRelease.bind(self)
}
}) : null,
self.next_release && self.last_release ? new Element('span.or', {
'text': ','
}) : null,
self.next_release ? [new Element('a.button.green', {
'text': self.last_release ? 'another release' : 'the best release',
'events': {
'click': self.tryNextRelease.bind(self)
}
}),
new Element('span.or', {
'text': 'or pick one below'
})] : null
)
}
}
@@ -91,10 +91,15 @@
.movie_result {
overflow: hidden;
height: 140px;
position: relative;
}
.movie_result .options {
height: 140px;
position: absolute;
height: 100%;
width: 100%;
top: 0;
left: 0;
border: 1px solid transparent;
border-width: 1px 0;
border-radius: 0;
@@ -133,17 +138,21 @@
.movie_result .data {
padding: 0 15px;
width: 470px;
position: relative;
height: 140px;
position: absolute;
height: 100%;
width: 100%;
top: 0;
margin: -140px 0 0 0;
left: 0;
background: #5c697b;
cursor: pointer;
border-bottom: 1px solid #333;
border-top: 1px solid rgba(255,255,255, 0.15);
transition: all .6s cubic-bezier(0.9,0,0.1,1);
}
.movie_result .data.open {
left: 100%;
}
.movie_result:last-child .data { border-bottom: 0; }
@@ -193,4 +202,9 @@
.search_form .mask {
border-radius: 3px;
position: absolute;
height: 100%;
width: 100%;
left: 0;
top: 0;
}
+25 -49
View File
@@ -19,7 +19,9 @@ Block.Search = new Class({
self.hideResults(false)
},
'blur': function(){
self.el.removeClass('focused')
(function(){
self.el.removeClass('focused')
}).delay(2000);
}
}
}),
@@ -117,7 +119,7 @@ Block.Search = new Class({
self.hideResults(false);
if(!cache){
self.positionMask().fade('in');
self.mask.fade('in');
if(!self.spinner)
self.spinner = createSpinner(self.mask);
@@ -139,7 +141,6 @@ Block.Search = new Class({
fill: function(q, json){
var self = this;
self.positionMask()
self.cache[q] = json
self.movies = {}
@@ -168,19 +169,6 @@ Block.Search = new Class({
},
positionMask: function(){
var self = this;
var s = self.result_container.getSize()
return self.mask.setStyles({
'width': s.x,
'height': s.y
}).position({
'relativeTo': self.result_container
})
},
loading: function(bool){
this.el[bool ? 'addClass' : 'removeClass']('loading')
},
@@ -193,7 +181,7 @@ Block.Search = new Class({
Block.Search.Item = new Class({
initialize: function(info){
initialize: function(info, options){
var self = this;
self.info = info;
@@ -203,14 +191,13 @@ Block.Search.Item = new Class({
},
create: function(){
var self = this;
var info = self.info;
var self = this,
info = self.info;
self.el = new Element('div.movie_result', {
'id': info.imdb
}).adopt(
self.options = new Element('div.options.inlay'),
self.options_el = new Element('div.options.inlay'),
self.data_container = new Element('div.data', {
'tween': {
duration: 400,
@@ -273,11 +260,7 @@ Block.Search.Item = new Class({
self.createOptions();
if(!self.width)
self.width = self.data_container.getCoordinates().width
self.data_container.tween('left', 0, self.width);
self.data_container.addClass('open');
self.el.addEvent('outerClick', self.closeOptions.bind(self))
},
@@ -285,7 +268,7 @@ Block.Search.Item = new Class({
closeOptions: function(){
var self = this;
self.data_container.tween('left', self.width, 0);
self.data_container.removeClass('open');
self.el.removeEvents('outerClick')
},
@@ -302,28 +285,31 @@ Block.Search.Item = new Class({
'profile_id': self.profile_select.get('value')
},
'onComplete': function(json){
self.options.empty();
self.options.adopt(
self.options_el.empty();
self.options_el.adopt(
new Element('div.message', {
'text': json.added ? 'Movie succesfully added.' : 'Movie didn\'t add properly. Check logs'
'text': json.added ? 'Movie successfully added.' : 'Movie didn\'t add properly. Check logs'
})
);
self.mask.fade('out');
},
'onFailure': function(){
self.options.empty();
self.options.adopt(
self.options_el.empty();
self.options_el.adopt(
new Element('div.message', {
'text': 'Something went wrong, check the logs for more info.'
})
);
self.mask.fade('out');
}
});
},
createOptions: function(){
var self = this;
var self = this,
info = self.info;
if(!self.options.hasClass('set')){
if(!self.options_el.hasClass('set')){
if(self.info.in_library){
var in_library = [];
@@ -332,10 +318,10 @@ Block.Search.Item = new Class({
});
}
self.options.adopt(
self.options_el.grab(
new Element('div').adopt(
self.option_thumbnail = self.info.images && self.info.images.poster.length > 0 ? new Element('img.thumbnail', {
'src': self.info.images.poster[0],
self.thumbnail = (info.images && info.images.poster.length > 0) ? new Element('img.thumbnail', {
'src': info.images.poster[0],
'height': null,
'width': null
}) : null,
@@ -372,7 +358,7 @@ Block.Search.Item = new Class({
}).inject(self.profile_select)
});
self.options.addClass('set');
self.options_el.addClass('set');
}
},
@@ -380,17 +366,7 @@ Block.Search.Item = new Class({
loadingMask: function(){
var self = this;
var s = self.options.getSize();
self.mask = new Element('span.mask', {
'styles': {
'position': 'relative',
'width': s.x,
'height': s.y,
'top': -s.y,
'display': 'block'
}
}).inject(self.options).fade('hide')
self.mask = new Element('span.mask').inject(self.el).fade('hide')
createSpinner(self.mask)
self.mask.fade('in')
+1 -1
View File
@@ -26,7 +26,7 @@ class QualityPlugin(Plugin):
{'identifier': 'scr', 'size': (600, 1600), 'label': 'Screener', 'alternative': ['screener', 'dvdscr', 'ppvrip'], 'allow': ['dvdr', 'dvd'], 'ext':['avi', 'mpg', 'mpeg']},
{'identifier': 'r5', 'size': (600, 1000), 'label': 'R5', 'alternative': [], 'allow': ['dvdr'], 'ext':['avi', 'mpg', 'mpeg']},
{'identifier': 'tc', 'size': (600, 1000), 'label': 'TeleCine', 'alternative': ['telecine'], 'allow': [], 'ext':['avi', 'mpg', 'mpeg']},
{'identifier': 'ts', 'size': (600, 1000), 'label': 'TeleSync', 'alternative': ['telesync'], 'allow': [], 'ext':['avi', 'mpg', 'mpeg']},
{'identifier': 'ts', 'size': (600, 1000), 'label': 'TeleSync', 'alternative': ['telesync', 'hdts'], 'allow': [], 'ext':['avi', 'mpg', 'mpeg']},
{'identifier': 'cam', 'size': (600, 1000), 'label': 'Cam', 'alternative': ['camrip', 'hdcam'], 'allow': [], 'ext':['avi', 'mpg', 'mpeg']}
]
pre_releases = ['cam', 'ts', 'tc', 'r5', 'scr']
+5 -2
View File
@@ -34,8 +34,11 @@ class Renamer(Plugin):
addEvent('app.load', self.scan)
fireEvent('schedule.interval', 'renamer.check_snatched', self.checkSnatched, minutes = self.conf('run_every'))
fireEvent('schedule.interval', 'renamer.check_snatched_forced', self.scan, hours = self.conf('force_every'))
if self.conf('run_every') > 0:
fireEvent('schedule.interval', 'renamer.check_snatched', self.checkSnatched, minutes = self.conf('run_every'))
if self.conf('force_every') > 0:
fireEvent('schedule.interval', 'renamer.check_snatched_forced', self.scan, hours = self.conf('force_every'))
def scanView(self):
+1 -1
View File
@@ -239,7 +239,7 @@ class Searcher(Plugin):
filedata = None
if data.get('download') and (ismethod(data.get('download')) or isfunction(data.get('download'))):
filedata = data.get('download')(url = data.get('url'), nzb_id = data.get('id'))
if filedata is 'try_next':
if filedata == 'try_next':
return filedata
successful = fireEvent('download', data = data, movie = movie, manual = manual, filedata = filedata, single = True)
@@ -21,6 +21,7 @@ class Userscript(Plugin):
addApiView('userscript.get/<random>/<path:filename>', self.getUserScript, static = True)
addApiView('userscript', self.iFrame)
addApiView('userscript.add_via_url', self.getViaUrl)
addApiView('userscript.includes', self.getIncludes)
addApiView('userscript.bookmark', self.bookmark)
addEvent('userscript.get_version', self.getVersion)
@@ -35,6 +36,13 @@ class Userscript(Plugin):
return self.renderTemplate(__file__, 'bookmark.js', **params)
def getIncludes(self):
return jsonified({
'includes': fireEvent('userscript.get_includes', merge = True),
'excludes': fireEvent('userscript.get_excludes', merge = True),
})
def getUserScript(self, random = '', filename = ''):
params = {
+7 -1
View File
@@ -6,6 +6,7 @@ from couchpotato.environment import Env
from urlparse import urlparse
import re
import time
import traceback
log = CPLog(__name__)
@@ -56,7 +57,12 @@ class YarrProvider(Provider):
addEvent('nzb.feed', self.feed)
def download(self, url = '', nzb_id = ''):
return self.urlopen(url)
try:
return self.urlopen(url, headers = {'User-Agent': Env.getIdentifier()}, show_error = False)
except:
log.error('Failed getting nzb from %s: %s', (self.getName(), traceback.format_exc()))
return 'try_next'
def feed(self):
return []
@@ -31,6 +31,14 @@ config = [{
'advanced': True,
'description': '<strong>%s</strong> is the rootname of the movie. For example "/path/to/movie cd1.mkv" will be "/path/to/movie"'
},
{
'name': 'meta_url_only',
'label': 'Only IMDB URL',
'default': False,
'advanced': True,
'description': 'Create a nfo with only the IMDB url inside',
'type': 'bool',
},
{
'name': 'meta_fanart',
'label': 'Fanart',
@@ -28,6 +28,11 @@ class XBMC(MetaDataBase):
return os.path.join(root, basename.replace('%s', name))
def getNfo(self, movie_info = {}, data = {}):
# return imdb url only
if self.conf('meta_url_only'):
return 'http://www.imdb.com/title/%s/' % toUnicode(data['library']['identifier'])
nfoxml = Element('movie')
# Title
@@ -1,23 +0,0 @@
from .main import Mysterbin
def start():
return Mysterbin()
config = [{
'name': 'mysterbin',
'groups': [
{
'tab': 'searcher',
'subtab': 'nzb_providers',
'name': 'Mysterbin',
'description': 'Free provider, less accurate. See <a href="https://www.mysterbin.com/">Mysterbin</a>',
'options': [
{
'name': 'enabled',
'type': 'enabler',
'default': True,
},
],
},
],
}]
@@ -1,102 +0,0 @@
from bs4 import BeautifulSoup
from couchpotato.core.event import fireEvent
from couchpotato.core.helpers.encoding import toUnicode, tryUrlencode, \
simplifyString
from couchpotato.core.helpers.variable import tryInt, getTitle
from couchpotato.core.logger import CPLog
from couchpotato.core.providers.nzb.base import NZBProvider
from couchpotato.environment import Env
log = CPLog(__name__)
class Mysterbin(NZBProvider):
urls = {
'search': 'https://www.mysterbin.com/advsearch?%s',
'download': 'https://www.mysterbin.com/nzb?c=%s',
'nfo': 'https://www.mysterbin.com/nfo?c=%s',
}
http_time_between_calls = 1 #seconds
def search(self, movie, quality):
results = []
if self.isDisabled():
return results
q = '"%s" %s %s' % (simplifyString(getTitle(movie['library'])), movie['library']['year'], quality.get('identifier'))
for ignored in Env.setting('ignored_words', 'searcher').split(','):
if len(q) + len(ignored.strip()) > 126:
break
q = '%s -%s' % (q, ignored.strip())
params = {
'q': q,
'match': 'normal',
'minSize': quality.get('size_min'),
'maxSize': quality.get('size_max'),
'complete': 2,
'maxAge': Env.setting('retention', 'nzb'),
'nopasswd': 'on',
}
cache_key = 'mysterbin.%s.%s.%s' % (movie['library']['identifier'], quality.get('identifier'), q)
data = self.getCache(cache_key, self.urls['search'] % tryUrlencode(params))
if data:
try:
html = BeautifulSoup(data)
resultable = html.find('table', attrs = {'class':'t'})
for result in resultable.find_all('tr'):
try:
myster_id = result.find('input', attrs = {'class': 'check4nzb'})['value']
# Age
age = ''
for temp in result.find('td', attrs = {'class': 'cdetail'}).find_all(text = True):
if 'days' in temp:
age = tryInt(temp.split(' ')[0])
break
# size
size = None
for temp in result.find('div', attrs = {'class': 'cdetail'}).find_all(text = True):
if 'gb' in temp.lower() or 'mb' in temp.lower() or 'kb' in temp.lower():
size = self.parseSize(temp)
break
description = ''
if result.find('a', text = 'View NFO'):
description = toUnicode(self.getCache('mysterbin.%s' % myster_id, self.urls['nfo'] % myster_id, cache_timeout = 25920000))
new = {
'id': myster_id,
'name': ''.join(result.find('span', attrs = {'class': 'cname'}).find_all(text = True)),
'type': 'nzb',
'provider': self.getName(),
'age': age,
'size': size,
'url': self.urls['download'] % myster_id,
'description': description,
'download': self.download,
'check_nzb': False,
}
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 = True)
if is_correct_movie:
results.append(new)
self.found(new)
except:
pass
return results
except AttributeError:
log.debug('No search results found.')
return results
@@ -1,32 +0,0 @@
from .main import Newzbin
def start():
return Newzbin()
config = [{
'name': 'newzbin',
'groups': [
{
'tab': 'searcher',
'subtab': 'nzb_providers',
'name': 'newzbin',
'description': 'See <a href="https://www.newzbin2.es/">Newzbin</a>',
'wizard': True,
'options': [
{
'name': 'enabled',
'type': 'enabler',
},
{
'name': 'username',
'default': '',
},
{
'name': 'password',
'default': '',
'type': 'password',
},
],
},
],
}]
@@ -1,156 +0,0 @@
from couchpotato.core.event import fireEvent
from couchpotato.core.helpers.encoding import 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 base64
import time
import xml.etree.ElementTree as XMLTree
log = CPLog(__name__)
class Newzbin(NZBProvider, RSS):
urls = {
'download': 'https://www.newzbin2.es/api/dnzb/',
'search': 'https://www.newzbin2.es/search/',
}
format_ids = {
2: ['scr'],
1: ['cam'],
4: ['tc'],
8: ['ts'],
1024: ['r5'],
}
cat_ids = [
([262144], ['bd50']),
([2097152], ['1080p']),
([524288], ['720p']),
([262144], ['brrip']),
([2], ['dvdr']),
]
cat_backup_id = -1
http_time_between_calls = 3 # Seconds
def search(self, movie, quality):
results = []
if self.isDisabled():
return results
format_id = self.getFormatId(type)
cat_id = self.getCatId(type)
arguments = tryUrlencode({
'searchaction': 'Search',
'u_url_posts_only': '0',
'u_show_passworded': '0',
'q_url': 'imdb.com/title/' + movie['library']['identifier'],
'sort': 'ps_totalsize',
'order': 'asc',
'u_post_results_amt': '100',
'feed': 'rss',
'category': '6',
'ps_rb_video_format': str(cat_id),
'ps_rb_source': str(format_id),
'u_post_larger_than': quality.get('size_min'),
'u_post_smaller_than': quality.get('size_max'),
})
url = "%s?%s" % (self.urls['search'], arguments)
cache_key = str('newzbin.%s.%s.%s' % (movie['library']['identifier'], str(format_id), str(cat_id)))
data = self.getCache(cache_key)
if not data:
headers = {
'Authorization': "Basic %s" % base64.encodestring('%s:%s' % (self.conf('username'), self.conf('password')))[:-1]
}
try:
data = self.urlopen(url, headers = headers)
self.setCache(cache_key, data)
except:
return results
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:
title = self.getTextElement(nzb, "title")
if 'error' in title.lower(): continue
REPORT_NS = 'http://www.newzbin2.es/DTD/2007/feeds/report/';
# Add attributes to name
try:
for attr in nzb.find('{%s}attributes' % REPORT_NS):
title += ' ' + attr.text
except:
pass
id = int(self.getTextElement(nzb, '{%s}id' % REPORT_NS))
size = str(int(self.getTextElement(nzb, '{%s}size' % REPORT_NS)) / 1024 / 1024) + ' mb'
date = str(self.getTextElement(nzb, '{%s}postdate' % REPORT_NS))
new = {
'id': id,
'type': 'nzb',
'provider': self.getName(),
'name': title,
'age': self.calculateAge(int(time.mktime(parse(date).timetuple()))),
'size': self.parseSize(size),
'url': str(self.getTextElement(nzb, '{%s}nzb' % REPORT_NS)),
'download': self.download,
'detail_url': str(self.getTextElement(nzb, 'link')),
'description': self.getTextElement(nzb, "description"),
'check_nzb': False,
}
is_correct_movie = fireEvent('searcher.correct_movie',
nzb = new, movie = movie, quality = quality,
imdb_results = True, single = True)
if is_correct_movie:
new['score'] = fireEvent('score.calculate', new, movie, single = True)
results.append(new)
self.found(new)
return results
except SyntaxError:
log.error('Failed to parse XML response from newzbin')
return results
def download(self, url = '', nzb_id = ''):
try:
log.info('Download nzb from newzbin, report id: %s ', nzb_id)
return self.urlopen(self.urls['download'], params = {
'username' : self.conf('username'),
'password' : self.conf('password'),
'reportid' : nzb_id
}, show_error = False)
except Exception, e:
log.error('Failed downloading from newzbin, check credit: %s', e)
return False
def getFormatId(self, format):
for id, quality in self.format_ids.iteritems():
for q in quality:
if q == format:
return id
return self.cat_backup_id
def isEnabled(self):
return NZBProvider.isEnabled(self) and self.conf('enabled') and self.conf('username') and self.conf('password')
@@ -219,4 +219,5 @@ class Newznab(NZBProvider, RSS):
return 'try_next'
log.error('Failed download from %s', (host, traceback.format_exc()))
raise
return 'try_next'
@@ -98,9 +98,6 @@ class NZBMatrix(NZBProvider, RSS):
return results
def download(self, url = '', nzb_id = ''):
return self.urlopen(url, headers = {'User-Agent': Env.getIdentifier()})
def getApiExt(self):
return '&username=%s&apikey=%s' % (self.conf('username'), self.conf('api_key'))
@@ -97,8 +97,5 @@ class Nzbsrus(NZBProvider, RSS):
return results
def download(self, url = '', nzb_id = ''):
return self.urlopen(url, headers = {'User-Agent': Env.getIdentifier()})
def getApiExt(self):
return '/%s/' % (self.conf('userid'))
@@ -57,7 +57,7 @@ class ThePirateBay(TorrentProvider):
data = ''
try:
data = self.urlopen(proxy, timeout = 3)
data = self.urlopen(proxy, timeout = 3, show_error = False)
except:
log.debug('Failed tpb proxy %s', proxy)
@@ -88,12 +88,20 @@ class ThePirateBay(TorrentProvider):
try:
soup = BeautifulSoup(data)
results_table = soup.find('table', attrs = {'id': 'searchResult'})
if not results_table:
return results
entries = results_table.find_all('tr')
for result in entries[1:]:
for result in entries[2:]:
link = result.find(href = re.compile('torrent\/\d+\/'))
download = result.find(href = re.compile('magnet:'))
size = re.search('Size (?P<size>.+),', unicode(result.select('font.detDesc')[0])).group('size')
try:
size = re.search('Size (?P<size>.+),', unicode(result.select('font.detDesc')[0])).group('size')
except:
continue
if link and download:
def extra_score(item):
@@ -0,0 +1,6 @@
from .main import Filmweb
def start():
return Filmweb()
config = []
@@ -0,0 +1,28 @@
from couchpotato.core.providers.userscript.base import UserscriptBase
import re
class Filmweb(UserscriptBase):
includes = ['http://www.filmweb.pl/*']
def getMovie(self, url):
cookie = {'Cookie': 'welcomeScreen=welcome_screen'}
try:
data = self.urlopen(url, headers = cookie)
except:
return
name = re.search("<h2.*?class=\"text-large caption\">(?P<name>[^<]+)</h2>", data)
if name is None:
name = re.search("<a.*?property=\"v:name\".*?>(?P<name>[^<]+)</a>", data)
name = name.group('name').decode('string_escape')
year = re.search("<span.*?id=filmYear.*?>\((?P<year>[^\)]+)\).*?</span>", data)
year = year.group('year')
return self.search(name, year)
+2
View File
@@ -55,6 +55,8 @@
'is_remote': false
});
$(document.body).set('data-api', window.location.protocol + '//' + window.location.host + Api.createUrl().replace('/default/', '/'));
// Catch errors
window.onerror = function(message, file, line){
+5 -5
View File
@@ -11,11 +11,6 @@
# Source function library.
. /etc/init.d/functions
# Source couchpotato configuration
if [ -f /etc/sysconfig/couchpotato ]; then
. /etc/sysconfig/couchpotato
fi
prog=couchpotato
lockfile=/var/lock/subsys/$prog
@@ -27,6 +22,11 @@ datadir=${CP_DATA-~/.couchpotato}
pidfile=${CP_PIDFILE-/var/run/couchpotato/couchpotato.pid}
##
# Source couchpotato configuration
if [ -f /etc/sysconfig/couchpotato ]; then
. /etc/sysconfig/couchpotato
fi
pidpath=`dirname ${pidfile}`
options=" --daemon --pid_file=${pidfile} --data_dir=${datadir}"