Merge branch 'refs/heads/develop'

This commit is contained in:
Ruud
2013-05-28 21:15:04 +02:00
12 changed files with 193 additions and 67 deletions

View File

@@ -36,12 +36,7 @@ class Transmission(Downloader):
if len(self.conf('directory', default = '')) > 0:
folder_name = self.createFileName(data, filedata, movie)[:-len(data.get('type')) - 1]
folder_path = os.path.join(self.conf('directory', default = ''), folder_name).rstrip(os.path.sep)
# Create the empty folder to download too
self.makeDir(folder_path)
params['download-dir'] = folder_path
params['download-dir'] = os.path.join(self.conf('directory', default = ''), folder_name).rstrip(os.path.sep)
torrent_params = {}
if self.conf('ratio'):
@@ -93,11 +88,13 @@ class Transmission(Downloader):
'fields': ['id', 'name', 'hashString', 'percentDone', 'status', 'eta', 'isFinished', 'downloadDir', 'uploadRatio']
}
queue = trpc.get_alltorrents(return_params)
except Exception, err:
log.error('Failed getting queue: %s', err)
return False
if not queue:
return []
statuses = StatusList(self)
# Get torrents status

View File

@@ -9,7 +9,6 @@ from multipartpost import MultipartPostHandler
import cookielib
import httplib
import json
import os
import re
import time
import urllib
@@ -106,36 +105,6 @@ class uTorrent(Downloader):
return False
statuses = StatusList(self)
download_folder = ''
settings_dict = {}
try:
data = self.utorrent_api.get_settings()
utorrent_settings = json.loads(data)
# Create settings dict
for item in utorrent_settings['settings']:
if item[1] == 0: # int
settings_dict[item[0]] = int(item[2] if not item[2].strip() == '' else '0')
elif item[1] == 1: # bool
settings_dict[item[0]] = True if item[2] == 'true' else False
elif item[1] == 2: # string
settings_dict[item[0]] = item[2]
log.debug('uTorrent settings: %s, %s', (settings_dict['dir_completed_download_flag'], settings_dict['dir_active_download_flag']))
# Get the download path from the uTorrent settings
if settings_dict['dir_completed_download_flag']:
download_folder = settings_dict['dir_completed_download']
elif settings_dict['dir_active_download_flag']:
download_folder = settings_dict['dir_active_download']
else:
log.info('No download folder set in uTorrent. Please set a download folder')
return False
except Exception, err:
log.error('Failed to get settings from uTorrent: %s', err)
return False
# Get torrents
for item in queue.get('torrents', []):
@@ -145,18 +114,13 @@ class uTorrent(Downloader):
if item[21] == 'Finished' or item[21] == 'Seeding':
status = 'completed'
if settings_dict['dir_add_label']:
release_folder = os.path.join(download_folder, item[11], item[2])
else:
release_folder = os.path.join(download_folder, item[2])
statuses.append({
'id': item[0],
'name': item[2],
'status': status,
'original_status': item[1],
'timeleft': str(timedelta(seconds = item[10])),
'folder': release_folder,
'folder': item[26],
})
return statuses
@@ -236,4 +200,22 @@ class uTorrentAPI(object):
def get_settings(self):
action = "action=getsettings"
return self._request(action)
settings_dict = {}
try:
utorrent_settings = json.loads(self._request(action))
# Create settings dict
for item in utorrent_settings['settings']:
if item[1] == 0: # int
settings_dict[item[0]] = int(item[2] if not item[2].strip() == '' else '0')
elif item[1] == 1: # bool
settings_dict[item[0]] = True if item[2] == 'true' else False
elif item[1] == 2: # string
settings_dict[item[0]] = item[2]
#log.debug('uTorrent settings: %s', settings_dict)
except Exception, err:
log.error('Failed to get settings from uTorrent: %s', err)
return settings_dict

View File

@@ -28,6 +28,7 @@ class Plugin(object):
_needs_shutdown = False
user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:24.0) Gecko/20130519 Firefox/24.0'
http_last_use = {}
http_time_between_calls = 0
http_failed_request = {}
@@ -106,7 +107,7 @@ class Plugin(object):
# Fill in some headers
headers['Referer'] = headers.get('Referer', urlparse(url).hostname)
headers['Host'] = headers.get('Host', urlparse(url).hostname)
headers['User-Agent'] = headers.get('User-Agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:10.0.2) Gecko/20100101 Firefox/10.0.2')
headers['User-Agent'] = headers.get('User-Agent', self.user_agent)
headers['Accept-encoding'] = headers.get('Accept-encoding', 'gzip')
host = urlparse(url).hostname
@@ -138,7 +139,7 @@ class Plugin(object):
response = opener.open(request, timeout = timeout)
else:
log.info('Opening url: %s, params: %s', (url, [x for x in params.iterkeys()]))
log.info('Opening url: %s, params: %s', (url, [x for x in params.iterkeys()] if isinstance(params, dict) else 'with data'))
data = tryUrlencode(params) if len(params) > 0 else None
request = urllib2.Request(url, data, headers)

View File

@@ -8,7 +8,6 @@ from couchpotato.core.logger import CPLog
from couchpotato.core.plugins.base import Plugin
from couchpotato.core.settings.model import Quality, Profile, ProfileType
from sqlalchemy.sql.expression import or_
import os.path
import re
import time
@@ -25,7 +24,7 @@ class QualityPlugin(Plugin):
{'identifier': 'dvdr', 'size': (3000, 10000), 'label': 'DVD-R', 'alternative': [], 'allow': [], 'ext':['iso', 'img'], 'tags': ['pal', 'ntsc', 'video_ts', 'audio_ts']},
{'identifier': 'dvdrip', 'size': (600, 2400), 'label': 'DVD-Rip', 'width': 720, 'alternative': ['dvdrip'], 'allow': [], 'ext':['avi', 'mpg', 'mpeg'], 'tags': [('dvd', 'rip'), ('dvd', 'xvid'), ('dvd', 'divx')]},
{'identifier': 'scr', 'size': (600, 1600), 'label': 'Screener', 'alternative': ['screener', 'dvdscr', 'ppvrip', 'dvdscreener'], 'allow': ['dvdr', 'dvd'], 'ext':['avi', 'mpg', 'mpeg']},
{'identifier': 'r5', 'size': (600, 1000), 'label': 'R5', 'alternative': [], 'allow': ['dvdr'], 'ext':['avi', 'mpg', 'mpeg']},
{'identifier': 'r5', 'size': (600, 1000), 'label': 'R5', 'alternative': ['r6'], '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', 'hdts'], 'allow': [], 'ext':['avi', 'mpg', 'mpeg']},
{'identifier': 'cam', 'size': (600, 1000), 'label': 'Cam', 'alternative': ['camrip', 'hdcam'], 'allow': [], 'ext':['avi', 'mpg', 'mpeg']}

View File

@@ -4,7 +4,7 @@ from couchpotato.core.event import addEvent, fireEvent, fireEventAsync
from couchpotato.core.helpers.encoding import toUnicode, ss
from couchpotato.core.helpers.request import getParams, jsonified
from couchpotato.core.helpers.variable import getExt, mergeDicts, getTitle, \
getImdb, link, symlink
getImdb, link, symlink, tryInt
from couchpotato.core.logger import CPLog
from couchpotato.core.plugins.base import Plugin
from couchpotato.core.settings.model import Library, File, Profile, Release, \
@@ -25,10 +25,10 @@ class Renamer(Plugin):
checking_snatched = False
def __init__(self):
addApiView('renamer.scan', self.scanView, docs = {
'desc': 'For the renamer to check for new files to rename in a folder',
'params': {
'async': {'desc': 'Optional: Set to 1 if you dont want to fire the renamer.scan asynchronous.'},
'movie_folder': {'desc': 'Optional: The folder of the movie to scan. Keep empty for default renamer folder.'},
'downloader' : {'desc': 'Optional: The downloader this movie has been downloaded with'},
'download_id': {'desc': 'Optional: The downloader\'s nzb/torrent ID'},
@@ -62,11 +62,14 @@ class Renamer(Plugin):
def scanView(self):
params = getParams()
async = tryInt(params.get('async', None))
movie_folder = params.get('movie_folder', None)
downloader = params.get('downloader', None)
download_id = params.get('download_id', None)
fireEventAsync('renamer.scan',
fire_handle = fireEvent if not async else fireEventAsync
fire_handle('renamer.scan',
movie_folder = movie_folder,
download_info = {'id': download_id, 'downloader': downloader} if download_id else None
)

View File

@@ -104,7 +104,7 @@ class YarrProvider(Provider):
try:
cookiejar = cookielib.CookieJar()
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookiejar))
opener.addheaders = []
opener.addheaders = [('User-Agent', self.user_agent)]
urllib2.install_opener(opener)
log.info2('Logging into %s', self.urls['login'])
f = opener.open(self.urls['login'], self.getLoginParams())
@@ -114,9 +114,12 @@ class YarrProvider(Provider):
if self.loginSuccess(output):
self.login_opener = opener
return True
except:
log.error('Failed to login %s: %s', (self.getName(), traceback.format_exc()))
error = 'unknown'
except:
error = traceback.format_exc()
log.error('Failed to login %s: %s', (self.getName(), error))
return False
def loginSuccess(self, output):

View File

@@ -14,13 +14,13 @@ log = CPLog(__name__)
class CouchPotatoApi(MovieProvider):
urls = {
'search': 'https://couchpota.to/api/search/%s/',
'info': 'https://couchpota.to/api/info/%s/',
'is_movie': 'https://couchpota.to/api/ismovie/%s/',
'eta': 'https://couchpota.to/api/eta/%s/',
'suggest': 'https://couchpota.to/api/suggest/',
'updater': 'https://couchpota.to/api/updater/?%s',
'messages': 'https://couchpota.to/api/messages/?%s',
'search': 'https://api.couchpota.to/search/%s/',
'info': 'https://api.couchpota.to/info/%s/',
'is_movie': 'https://api.couchpota.to/ismovie/%s/',
'eta': 'https://api.couchpota.to/eta/%s/',
'suggest': 'https://api.couchpota.to/suggest/',
'updater': 'https://api.couchpota.to/updater/?%s',
'messages': 'https://api.couchpota.to/messages/?%s',
}
http_time_between_calls = 0
api_version = 1

View File

@@ -37,7 +37,7 @@ class TheMovieDb(MovieProvider):
if raw:
try:
results = self.parseMovie(raw)
log.info('Found: %s', results['titles'][0] + ' (' + str(results['year']) + ')')
log.info('Found: %s', results['titles'][0] + ' (' + str(results.get('year', 0)) + ')')
self.setCache(cache_key, results)
return results
@@ -81,7 +81,7 @@ class TheMovieDb(MovieProvider):
if nr == limit:
break
log.info('Found: %s', [result['titles'][0] + ' (' + str(result['year']) + ')' for result in results])
log.info('Found: %s', [result['titles'][0] + ' (' + str(result.get('year', 0)) + ')' for result in results])
self.setCache(cache_key, results)
return results

View File

@@ -0,0 +1,45 @@
from .main import HDBits
def start():
return HDBits()
config = [{
'name': 'hdbits',
'groups': [
{
'tab': 'searcher',
'subtab': 'providers',
'list': 'torrent_providers',
'name': 'HDBits',
'description': 'See <a href="http://hdbits.org">HDBits</a>',
'options': [
{
'name': 'enabled',
'type': 'enabler',
'default': False,
},
{
'name': 'username',
'default': '',
},
{
'name': 'password',
'default': '',
'type': 'password',
},
{
'name': 'passkey',
'default': '',
},
{
'name': 'extra_score',
'advanced': True,
'label': 'Extra Score',
'type': 'int',
'default': 0,
'description': 'Starting score for each release found via this provider.',
},
],
},
],
}]

View File

@@ -0,0 +1,55 @@
from bs4 import BeautifulSoup
from couchpotato.core.helpers.encoding import tryUrlencode
from couchpotato.core.helpers.variable import tryInt
from couchpotato.core.logger import CPLog
from couchpotato.core.providers.torrent.base import TorrentProvider
import traceback
log = CPLog(__name__)
class HDBits(TorrentProvider):
urls = {
'test' : 'https://hdbits.org/',
'login' : 'https://hdbits.org/login/doLogin/',
'detail' : 'https://hdbits.org/details.php?id=%s&source=browse',
'search' : 'https://hdbits.org/json_search.php?imdb=%s',
'download' : 'https://hdbits.org/download.php/%s.torrent?id=%s&passkey=%s&source=details.browse',
}
http_time_between_calls = 1 #seconds
def _search(self, movie, quality, results):
data = self.getJsonData(self.urls['search'] % movie['library']['identifier'], opener = self.login_opener)
if data:
try:
for result in data:
results.append({
'id': result['id'],
'name': result['title'],
'url': self.urls['download'] % (result['title'], result['id'], self.conf('passkey')),
'detail_url': self.urls['detail'] % result['id'],
'size': self.parseSize(result['size']),
'seeders': tryInt(result['seeder']),
'leechers': tryInt(result['leecher'])
})
except:
log.error('Failed getting results from %s: %s', (self.getName(), traceback.format_exc()))
def getLoginParams(self):
data = self.getHTMLData('https://hdbits.org/login')
bs = BeautifulSoup(data)
secret = bs.find('input', attrs = {'name': 'lol'})['value']
return tryUrlencode({
'uname': self.conf('username'),
'password': self.conf('password'),
'lol': secret
})
def loginSuccess(self, output):
return '/logout.php' in output.lower()

View File

@@ -38,6 +38,30 @@ config = [{
'name': 'passkey',
'default': '',
},
{
'name': 'prefer_golden',
'advanced': True,
'type': 'bool',
'label': 'Prefer golden',
'default': 1,
'description': 'Favors Golden Popcorn-releases over all other releases.'
},
{
'name': 'prefer_scene',
'advanced': True,
'type': 'bool',
'label': 'Prefer scene',
'default': 0,
'description': 'Favors scene-releases over non-scene releases.'
},
{
'name': 'require_approval',
'advanced': True,
'type': 'bool',
'label': 'Require approval',
'default': 0,
'description': 'Require staff-approval for releases to be accepted.'
},
{
'name': 'extra_score',
'advanced': True,

View File

@@ -103,11 +103,16 @@ class PassThePopcorn(TorrentProvider):
for torrent in ptpmovie['Torrents']:
torrent_id = tryInt(torrent['Id'])
torrentdesc = '%s %s %s' % (torrent['Resolution'], torrent['Source'], torrent['Codec'])
torrentscore = 0
if 'GoldenPopcorn' in torrent and torrent['GoldenPopcorn']:
torrentdesc += ' HQ'
if self.conf('prefer_golden'):
torrentscore += 200
if 'Scene' in torrent and torrent['Scene']:
torrentdesc += ' Scene'
if self.conf('prefer_scene'):
torrentscore += 50
if 'RemasterTitle' in torrent and torrent['RemasterTitle']:
torrentdesc += self.htmlToASCII(' %s' % torrent['RemasterTitle'])
@@ -115,18 +120,21 @@ class PassThePopcorn(TorrentProvider):
torrent_name = re.sub('[^A-Za-z0-9\-_ \(\).]+', '', '%s (%s) - %s' % (movie_title, ptpmovie['Year'], torrentdesc))
def extra_check(item):
return self.torrentMeetsQualitySpec(item, type)
return self.torrentMeetsQualitySpec(item, quality_id)
results.append({
'id': torrent_id,
'name': torrent_name,
'Source': torrent['Source'],
'Checked': 'true' if torrent['Checked'] else 'false',
'Resolution': torrent['Resolution'],
'url': '%s?action=download&id=%d&authkey=%s&torrent_pass=%s' % (self.urls['torrent'], torrent_id, authkey, passkey),
'detail_url': self.urls['detail'] % torrent_id,
'date': tryInt(time.mktime(parse(torrent['UploadTime']).timetuple())),
'size': tryInt(torrent['Size']) / (1024 * 1024),
'seeders': tryInt(torrent['Seeders']),
'leechers': tryInt(torrent['Leechers']),
'score': 50 if torrent['GoldenPopcorn'] else 0,
'score': torrentscore,
'extra_check': extra_check,
'download': self.loginDownload,
})
@@ -167,7 +175,13 @@ class PassThePopcorn(TorrentProvider):
if not quality in self.post_search_filters:
return True
for field, specs in self.post_search_filters[quality].items():
reqs = self.post_search_filters[quality].copy()
if self.conf('require_approval'):
log.debug('Config: Require staff-approval activated')
reqs['Checked'] = ['true']
for field, specs in reqs.items():
matches_one = False
seen_one = False
@@ -182,11 +196,14 @@ class PassThePopcorn(TorrentProvider):
return False
else:
# a positive rule; if any of the possible positive values match the field, return True
log.debug('Checking if torrents field %s equals %s' % (field, spec))
seen_one = True
if torrent[field] == spec:
log.debug('Torrent satisfied %s == %s' % (field, spec))
matches_one = True
if seen_one and not matches_one:
log.debug('Torrent did not satisfy requirements, ignoring')
return False
return True