Initial torrent support
Transmission downloader Code cleanup
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
from couchpotato.core.event import addEvent
|
||||
from couchpotato.core.helpers.encoding import toSafeString
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.plugins.base import Plugin
|
||||
from couchpotato.environment import Env
|
||||
from couchpotato.core.helpers.encoding import toSafeString
|
||||
import os
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
@@ -42,6 +42,6 @@ class Blackhole(Downloader):
|
||||
pass
|
||||
|
||||
except:
|
||||
log.debug('Failed to download file: %s' % data.get('name'))
|
||||
log.debug('Failed to download file %s: %s' % (data.get('name'), traceback.format_exc()))
|
||||
return False
|
||||
return False
|
||||
|
||||
@@ -29,6 +29,7 @@ config = [{
|
||||
},
|
||||
{
|
||||
'name': 'password',
|
||||
'type': 'password',
|
||||
},
|
||||
{
|
||||
'name': 'paused',
|
||||
@@ -43,6 +44,7 @@ config = [{
|
||||
{
|
||||
'name': 'ratio',
|
||||
'default': 10,
|
||||
'type': 'int',
|
||||
'advanced': True,
|
||||
'description': 'Stop transfer when reaching ratio',
|
||||
},
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from base64 import b64encode
|
||||
from couchpotato.core.downloaders.base import Downloader
|
||||
from couchpotato.core.helpers.encoding import isInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
@@ -17,7 +18,6 @@ class Transmission(Downloader):
|
||||
|
||||
log.info('Sending "%s" to Transmission.' % data.get('name'))
|
||||
|
||||
|
||||
# Load host from config and split out port.
|
||||
host = self.conf('host').split(':')
|
||||
if not isInt(host[1]):
|
||||
@@ -26,24 +26,21 @@ class Transmission(Downloader):
|
||||
|
||||
# Set parameters for Transmission
|
||||
params = {
|
||||
'paused': self.conf('paused', 0),
|
||||
'download_dir': self.conf('directory', None)
|
||||
}
|
||||
change_params = {
|
||||
'seedRatioLimit': self.conf('ratio'),
|
||||
'seedRatioMode': 1 if self.conf('ratio') else 0
|
||||
'paused': self.conf('paused', default = 0),
|
||||
'download_dir': self.conf('directory', default = None)
|
||||
}
|
||||
|
||||
try:
|
||||
tc = transmissionrpc.Client(host[0], port = host[1], user = self.conf('username'), password = self.conf('password'))
|
||||
tr_id = tc.add_uri(data.get('url'), **params)
|
||||
filedata = data.get('download')(url = data.get('url'), nzb_id = data.get('id'))
|
||||
torrent = tc.add_torrent(b64encode(filedata), **params)
|
||||
|
||||
# Change settings of added torrents
|
||||
for item in tr_id:
|
||||
try:
|
||||
tc.change(item, timeout = None, **change_params)
|
||||
except transmissionrpc.TransmissionError, e:
|
||||
log.error('Failed to change settings for transfer in transmission: %s' % e)
|
||||
try:
|
||||
torrent.seed_ratio_limit = self.conf('ratio')
|
||||
torrent.seed_ratio_mode = 'single' if self.conf('ratio') else 'global'
|
||||
except transmissionrpc.TransmissionError, e:
|
||||
log.error('Failed to change settings for transfer in transmission: %s' % e)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@@ -23,4 +23,12 @@ class Score(Plugin):
|
||||
|
||||
score += sizeScore(nzb['size'])
|
||||
|
||||
# Torrents only
|
||||
if nzb.get('seeds'):
|
||||
try:
|
||||
score += nzb.get('seeds') / 5
|
||||
score += nzb.get('leechers') / 10
|
||||
except:
|
||||
pass
|
||||
|
||||
return score
|
||||
|
||||
@@ -28,7 +28,7 @@ config = [{
|
||||
{
|
||||
'name': 'ignored_words',
|
||||
'label': 'Ignored words',
|
||||
'default': 'german, dutch, french, danish, swedish, dubbed, swesub, korsub',
|
||||
'default': 'german, dutch, french, danish, swedish, spanish, italian, korean, dubbed, swesub, korsub',
|
||||
},
|
||||
],
|
||||
}, {
|
||||
|
||||
@@ -161,7 +161,7 @@ class Searcher(Plugin):
|
||||
single_category = kwargs.get('single_category', False)
|
||||
retention = Env.setting('retention', section = 'nzb')
|
||||
|
||||
if retention < nzb.get('age', 0):
|
||||
if nzb.get('seeds') is None and retention < nzb.get('age', 0):
|
||||
log.info('Wrong: Outside retention, age is %s, needs %s or lower: %s' % (nzb['age'], retention, nzb['name']))
|
||||
return False
|
||||
|
||||
|
||||
@@ -48,6 +48,20 @@ class YarrProvider(Provider):
|
||||
def __init__(self):
|
||||
addEvent('provider.belongs_to', self.belongsTo)
|
||||
|
||||
addEvent('%s.search' % self.type, self.search)
|
||||
addEvent('yarr.search', self.search)
|
||||
|
||||
addEvent('nzb.feed', self.feed)
|
||||
|
||||
def download(self, url = '', nzb_id = ''):
|
||||
return self.urlopen(url)
|
||||
|
||||
def feed(self):
|
||||
return []
|
||||
|
||||
def search(self, movie, quality):
|
||||
return []
|
||||
|
||||
def belongsTo(self, url, host = None):
|
||||
try:
|
||||
hostname = urlparse(url).hostname
|
||||
|
||||
@@ -3,7 +3,7 @@ from couchpotato.core.helpers.variable import mergeDicts
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.plugins.base import Plugin
|
||||
import json
|
||||
import os.path
|
||||
import os
|
||||
import shutil
|
||||
import traceback
|
||||
|
||||
|
||||
@@ -6,22 +6,5 @@ import time
|
||||
class NZBProvider(YarrProvider):
|
||||
type = 'nzb'
|
||||
|
||||
def __init__(self):
|
||||
super(NZBProvider, self).__init__()
|
||||
|
||||
addEvent('nzb.search', self.search)
|
||||
addEvent('yarr.search', self.search)
|
||||
|
||||
addEvent('nzb.feed', self.feed)
|
||||
|
||||
def download(self, url = '', nzb_id = ''):
|
||||
return self.urlopen(url)
|
||||
|
||||
def feed(self):
|
||||
return []
|
||||
|
||||
def search(self, movie, quality):
|
||||
return []
|
||||
|
||||
def calculateAge(self, unix):
|
||||
return int(time.time() - unix) / 24 / 60 / 60
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from BeautifulSoup import BeautifulSoup, SoupStrainer
|
||||
from BeautifulSoup import BeautifulSoup
|
||||
from couchpotato.core.event import fireEvent
|
||||
from couchpotato.core.helpers.encoding import toUnicode
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
|
||||
@@ -3,4 +3,19 @@ from .main import KickAssTorrents
|
||||
def start():
|
||||
return KickAssTorrents()
|
||||
|
||||
config = []
|
||||
config = [{
|
||||
'name': 'kickasstorrents',
|
||||
'groups': [
|
||||
{
|
||||
'tab': 'providers',
|
||||
'name': 'KickAssTorrents',
|
||||
'options': [
|
||||
{
|
||||
'name': 'enabled',
|
||||
'type': 'enabler',
|
||||
'default': False,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}]
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
from BeautifulSoup import BeautifulSoup
|
||||
from couchpotato.core.event import fireEvent
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.torrent.base import TorrentProvider
|
||||
import StringIO
|
||||
import gzip
|
||||
import re
|
||||
import traceback
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
@@ -7,8 +14,124 @@ log = CPLog(__name__)
|
||||
class KickAssTorrents(TorrentProvider):
|
||||
|
||||
urls = {
|
||||
'download': 'http://torrents.thepiratebay.org/%s/%s.torrent',
|
||||
'test': 'http://www.kat.ph/',
|
||||
'detail': 'http://www.kat.ph/%s-t%s.html',
|
||||
'search': 'http://www.kat.ph/%s-i%s/',
|
||||
}
|
||||
|
||||
cat_ids = [
|
||||
(['cam'], ['cam']),
|
||||
(['telesync'], ['ts', 'tc']),
|
||||
(['screener', 'tvrip'], ['screener']),
|
||||
(['x264', '720p', '1080p', 'blu-ray', 'hdrip'], ['bd50', '1080p', '720p', 'brrip']),
|
||||
(['dvdrip'], ['dvdrip']),
|
||||
(['dvd'], ['dvdr']),
|
||||
]
|
||||
|
||||
http_time_between_calls = 1 #seconds
|
||||
|
||||
def search(self, movie, quality):
|
||||
|
||||
results = []
|
||||
if self.isDisabled() or not self.isAvailable(self.urls['test']):
|
||||
return results
|
||||
|
||||
cache_key = 'kickasstorrents.%s' % movie['library']['identifier']
|
||||
data = self.getCache(cache_key, self.urls['search'] % (movie['library']['titles'][0]['title'], movie['library']['identifier'].replace('tt', '')))
|
||||
if data:
|
||||
|
||||
cat_ids = self.getCatId(quality['identifier'])
|
||||
table_order = ['name', 'size', None, 'age', 'seeds', 'leechers']
|
||||
|
||||
try:
|
||||
html = BeautifulSoup(data)
|
||||
resultdiv = html.find('div', attrs = {'class':'tabs'})
|
||||
for result in resultdiv.findAll('div', recursive = False):
|
||||
if result.get('id').lower() not in cat_ids:
|
||||
continue
|
||||
|
||||
try:
|
||||
|
||||
try:
|
||||
for temp in result.findAll('tr'):
|
||||
if temp['class'] is 'firstr' or not temp.get('id'):
|
||||
continue
|
||||
|
||||
new = {
|
||||
'type': 'torrent',
|
||||
'check_nzb': False,
|
||||
'description': '',
|
||||
'provider': self.getName(),
|
||||
'download': self.download,
|
||||
'score': 0,
|
||||
}
|
||||
|
||||
nr = 0
|
||||
for td in temp.findAll('td'):
|
||||
column_name = table_order[nr]
|
||||
if column_name:
|
||||
|
||||
if column_name is 'name':
|
||||
link = td.find('div', {'class': 'torrentname'}).findAll('a')[1]
|
||||
new['id'] = temp.get('id')[-8:]
|
||||
new['name'] = link.text
|
||||
new['url'] = td.findAll('a', 'idownload')[1]['href']
|
||||
new['score'] = 20 if td.find('a', 'iverif') else 0
|
||||
elif column_name is 'size':
|
||||
new['size'] = self.parseSize(td.text)
|
||||
elif column_name is 'age':
|
||||
new['age'] = self.ageToDays(td.text)
|
||||
elif column_name is 'seeds':
|
||||
new['seeds'] = tryInt(td.text)
|
||||
elif column_name is 'leechers':
|
||||
new['leechers'] = tryInt(td.text)
|
||||
|
||||
nr += 1
|
||||
|
||||
new['score'] += fireEvent('score.calculate', new, movie, single = True)
|
||||
is_correct_movie = fireEvent('searcher.correct_movie',
|
||||
nzb = new, movie = movie, quality = quality,
|
||||
imdb_results = True, single_category = False, single = True)
|
||||
if is_correct_movie:
|
||||
results.append(new)
|
||||
self.found(new)
|
||||
except:
|
||||
log.error('Failed parsing KickAssTorrents: %s' % traceback.format_exc())
|
||||
except:
|
||||
pass
|
||||
|
||||
return results
|
||||
except AttributeError:
|
||||
log.debug('No search results found.')
|
||||
|
||||
return results
|
||||
|
||||
def ageToDays(self, age_str):
|
||||
age = 0
|
||||
age_str = age_str.replace(' ', ' ')
|
||||
|
||||
regex = '(\d*.?\d+).(sec|hour|day|week|month|year)+'
|
||||
matches = re.findall(regex, age_str)
|
||||
for match in matches:
|
||||
nr, size = match
|
||||
mult = 1
|
||||
if size == 'week':
|
||||
mult = 7
|
||||
elif size == 'month':
|
||||
mult = 30.5
|
||||
elif size == 'year':
|
||||
mult = 365
|
||||
|
||||
age += tryInt(nr) * mult
|
||||
|
||||
return tryInt(age)
|
||||
|
||||
def download(self, url = '', nzb_id = ''):
|
||||
compressed_data = super(KickAssTorrents, self).download(url = url, nzb_id = nzb_id)
|
||||
|
||||
compressedstream = StringIO.StringIO(compressed_data)
|
||||
gzipper = gzip.GzipFile(fileobj = compressedstream)
|
||||
data = gzipper.read()
|
||||
|
||||
return data
|
||||
|
||||
|
||||
Reference in New Issue
Block a user